Utilizzo di "debug printf"
È possibile lasciare che Emacs ti aiuti a capire modificando la definizione della funzione:
(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))))))
Basta aggiungere un (message ...)posto per avere una traccia stampata nel *Messages*buffer.
Usando Edebug
Posiziona il punto in qualsiasi punto all'interno della definizione della funzione e premi C-u C-M-xper "strumento". Quindi valutare la funzione, ad esempio posizionando il punto dopo (triangle-using-cond 3)e colpendo C-x C-e.
Ora sei in modalità Edebug. Premi la barra spaziatrice per scorrere la funzione. I valori intermedi di ciascuna espressione sono mostrati nell'area dell'eco. Per uscire dalla modalità Edebug basta premere q. Per rimuovere la strumentazione, posiziona un punto qualsiasi all'interno della definizione e premi C-M-xper rivalutare la definizione.
Utilizzo del debugger standard di Emacs
M-x debug-on-entry triangle-using-cond, quindi, quando triangle-using-condviene invocato, vieni inserito nel debugger (buffer *Backtrace*) di Emacs .
Passa attraverso la valutazione usando d(o cper saltare tutte le valutazioni poco interessanti).
Per visualizzare lo stato intermedio (valori variabili, ecc.) È possibile utilizzare in equalsiasi momento. Viene richiesto di inserire un sexp per valutare e il risultato della valutazione viene stampato.
Mentre usi il debugger, mantieni una copia del codice sorgente visibile in un altro frame, in modo da poter seguire quello che sta succedendo.
È inoltre possibile inserire chiamate esplicite per immettere il debugger (più o meno punti di interruzione) in posizioni arbitrarie nel codice sorgente. Inserisci (debug)o (debug nil SOME-SEXP-TO-EVALUATE). In quest'ultimo caso, quando viene inserito il debugger SOME-SEXP-TO-EVALUATEviene valutato e il risultato viene stampato. (Ricorda che puoi inserire tale codice nel codice sorgente e utilizzarlo C-M-xper valutarlo, quindi annullare: non è necessario salvare il file modificato.)
Vedere il manuale Elisp, nodo Using Debuggerper ulteriori informazioni.
Ricorsione come un ciclo
Ad ogni modo, pensa alla ricorsione come a un ciclo. Sono definiti due casi di risoluzione: (<= number 0)e (= number 1). In questi casi la funzione restituisce un numero semplice.
Nel caso ricorsivo la funzione restituisce la somma di quel numero e il risultato della funzione con number - 1. Alla fine, la funzione verrà chiamata con uno 1o un numero minore o uguale a zero.
Il risultato del caso ricorsivo è quindi:
(+ number (+ (1- number) (+ (1- (1- number)) ... 1)
Prendi ad esempio (triangle-using-cond 4). Accumuliamo l'espressione finale:
nella prima iterazione numberè 4, quindi il (> number 1)ramo è seguito. Iniziamo a costruire un'espressione (+ 4 ...e chiamiamo la funzione con (1- 4), ad es (triangle-using-cond 3).
ora numberè 3e il risultato è (+ 3 (triangle-using-cond 2)). L'espressione del risultato totale è (+ 4 (+ 3 (triangle-using-cond 2))).
numberè 2ora, quindi l'espressione è(+ 4 (+ 3 (+ 2 (triangle-using-cond 1))))
numberè 1ora e prendiamo il (= number 1)ramo, risultando noioso 1. L'intera espressione è (+ 4 (+ 3 (+ 2 1))). Valutare che dall'interno verso l'esterno e si ottiene: (+ 4 (+ 3 3)), (+ 4 6), o semplicemente 10.
triangle-using-condcon l'argomento 1 in meno di qualunque sia il numero. Le condizioni vanno nell'ordine di a, b, e quindi c - qualunque cosa corrisponda per prima, è dove il dollaro si ferma.