Uso de "depuración de printf"
Puede dejar que Emacs lo ayude a comprender modificando la definición de la función:
(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))))))
Simplemente agregue un (message ...)lugar para imprimir un rastro en el *Messages*búfer.
Usando Edebug
Coloque el punto en cualquier lugar dentro de la definición de la función y presione C-u C-M-xpara "instrumentarlo". Luego evalúe la función, por ejemplo, colocando un punto después (triangle-using-cond 3)y golpeando C-x C-e.
Ahora estás en modo Edebug. Presiona la barra espaciadora para recorrer la función. Los valores intermedios de cada expresión se muestran en el área de eco. Para salir del modo Edebug solo presiona q. Para eliminar la instrumentación, coloque el punto en cualquier lugar dentro de la definición y presione C-M-xpara reevaluar la definición.
Usando el depurador estándar de Emacs
M-x debug-on-entry triangle-using-cond, luego, cuando triangle-using-condse invoca, se le coloca en el depurador de Emacs (búfer *Backtrace*).
Avance por la evaluación usando d(o cpara omitir cualquier evaluación no interesante).
Para ver el estado intermedio (valores variables, etc.) puede usarlo en ecualquier momento. Se le solicita que ingrese un sexp para evaluar, y se imprime el resultado de la evaluación.
Mientras usa el depurador, mantenga una copia del código fuente visible en otro marco, para que pueda seguir lo que está sucediendo.
También puede insertar llamadas explícitas para ingresar el depurador (más o menos puntos de interrupción) en lugares arbitrarios en el código fuente. Usted inserta (debug)o (debug nil SOME-SEXP-TO-EVALUATE). En el último caso, cuando se ingresa el depurador SOME-SEXP-TO-EVALUATEse evalúa y se imprime el resultado. (Recuerde que puede insertar dicho código en el código fuente y utilizarlo C-M-xpara evaluarlo, luego deshacerlo; no necesita guardar el archivo editado).
Consulte el manual de Elisp, nodo Using Debuggerpara obtener más información.
La recursión como un bucle
De todos modos, piense en la recursividad como un bucle. Hay dos casos de terminación definidos: (<= number 0)y (= number 1). En estos casos, la función devuelve un número simple.
En el caso recursivo, la función devuelve la suma de ese número y el resultado de la función con number - 1. Eventualmente, la función se llamará con 1o con un número menor o igual a cero.
El resultado del caso recursivo es por lo tanto:
(+ number (+ (1- number) (+ (1- (1- number)) ... 1)
Toma por ejemplo (triangle-using-cond 4). Acumulemos la expresión final:
en la primera iteración numberes 4, entonces (> number 1)se sigue la rama. Comenzamos a construir una expresión (+ 4 ...y llamamos a la función con (1- 4), es decir (triangle-using-cond 3).
ahora numberes 3, y el resultado es (+ 3 (triangle-using-cond 2)). La expresión de resultado total es (+ 4 (+ 3 (triangle-using-cond 2))).
numberes 2ahora, entonces la expresión es(+ 4 (+ 3 (+ 2 (triangle-using-cond 1))))
numberes 1ahora, y tomamos la (= number 1)rama, lo que resulta en un aburrido 1. Toda la expresión es (+ 4 (+ 3 (+ 2 1))). Evaluar que de adentro hacia afuera y se obtiene: (+ 4 (+ 3 3)), (+ 4 6)o simplemente 10.
triangle-using-condcon el argumento 1 menor que cualquiera que sea el número. Las condiciones van en orden de a, b, y luego c - lo que coincida primero, es donde se detiene el dinero.