Using "printf debugging"
You could let Emacs help you understand by modifying the function definition:
(defun triangle-using-cond (number)
(message (format "called with %d" number))
(cond ((<= number 0) 0)
((= number 1) 1)
((> number 1)
(+ number (triangle-using-cond (1- number))))))
(message ...) somewhere to have a trail printed to the
Place point anywhere inside the function definition and hit
C-u C-M-x to "instrument" it. Then evaluate the function, e.g. by placing point after
(triangle-using-cond 3) and hitting
You are now in Edebug mode. Hit the space bar to step through the function. The intermediate values of each expression are shown in the echo area. To exit Edebug mode just hit
q. To remove the instrumentation, put point anywhere inside the definition and hit
C-M-x to re-evaluate the definition.
Using the standard Emacs debugger
M-x debug-on-entry triangle-using-cond, then, when
triangle-using-cond is invoked, you are placed in the Emacs debugger (buffer
Step through the evaluation using
c to skip through any uninteresting evaluations).
To see intermediate state (variable values, etc.) you can use
e anytime. You are prompted to enter a sexp to evaluate, and the evaluation result is printed.
While you use the debugger, keep a copy of the source code visible in another frame, so you can follow what's going on.
You can also insert explicit calls to enter the debugger (more or less breakpoints) at arbitrary places in the source code. You insert
(debug nil SOME-SEXP-TO-EVALUATE). In the latter case, when the debugger is entered
SOME-SEXP-TO-EVALUATE is evaluated and the result is printed. (Remember that you can insert such code into the source code and use
C-M-x to evaluate it, then undo - you need not save the edited file.)
See the Elisp manual, node
Using Debugger for more information.
Recursion as a loop
Anyway, think of recursion as a loop. There are two termination cases defined:
(<= number 0) and
(= number 1). In these cases the function returns a simple number.
In the recursive case the function returns the sum of that number and the result of the function with
number - 1. Eventually, the function will be called with either
1 or a number smaller than or equal to zero.
The recursive case result is hence:
(+ number (+ (1- number) (+ (1- (1- number)) ... 1)
Take for example
(triangle-using-cond 4). Let's accumulate the final expression:
in the first iteration
4, so the
(> number 1) branch is followed. We start building an expression
(+ 4 ... and call the function with
(1- 4), i.e.
3, and the result is
(+ 3 (triangle-using-cond 2)). The total result expression is
(+ 4 (+ 3 (triangle-using-cond 2))).
2 now, so the expression is
(+ 4 (+ 3 (+ 2 (triangle-using-cond 1))))
1 now, and we take the
(= number 1) branch, resulting in a boring
1. The whole expression is
(+ 4 (+ 3 (+ 2 1))). Evaluate that from the inside out and you get:
(+ 4 (+ 3 3)),
(+ 4 6), or just