Verwendung von "printf debugging"
Sie können sich von Emacs verständigen lassen, indem Sie die Funktionsdefinition ändern:
(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))))))
Fügen Sie einfach (message ...)
irgendwo hinzu, um eine Spur in den *Messages*
Puffer zu drucken .
Verwenden von Edebug
Platzieren Sie den Punkt irgendwo in der Funktionsdefinition und drücken Sie, um ihn C-u C-M-x
zu "instrumentieren". Bewerten Sie dann die Funktion, indem Sie z. B. einen Punkt nach dem anderen platzieren (triangle-using-cond 3)
und auf den anderen schlagen C-x C-e
.
Sie befinden sich jetzt im Edebug-Modus. Drücke die Leertaste, um die Funktion zu durchlaufen. Die Zwischenwerte der einzelnen Ausdrücke werden im Echobereich angezeigt. Um den Edebug-Modus zu verlassen, drücken Sie einfach q
. Um die Instrumentierung zu entfernen, platzieren Sie den Punkt an einer beliebigen Stelle in der Definition und drücken Sie C-M-x
, um die Definition neu zu bewerten.
Verwendung des Standard-Emacs-Debuggers
M-x debug-on-entry triangle-using-cond
Wenn triangle-using-cond
Sie dann aufgerufen werden, werden Sie in den Emacs-Debugger (Puffer *Backtrace*
) versetzt.
Durchlaufen Sie die Bewertung mit d
(oder c
, um uninteressante Bewertungen zu überspringen).
Den Zwischenzustand (variable Werte usw.) können Sie jederzeit e
anzeigen. Sie werden aufgefordert, ein Geschlecht für die Bewertung einzugeben, und das Bewertungsergebnis wird gedruckt.
Bewahren Sie während der Verwendung des Debuggers eine Kopie des Quellcodes in einem anderen Frame auf, damit Sie verfolgen können, was vor sich geht.
Sie können auch explizite Aufrufe einfügen, um den Debugger (mehr oder weniger Haltepunkte) an beliebigen Stellen im Quellcode einzugeben. Sie fügen (debug)
oder ein (debug nil SOME-SEXP-TO-EVALUATE)
. Im letzteren Fall wird bei Eingabe des Debuggers SOME-SEXP-TO-EVALUATE
ausgewertet und das Ergebnis ausgedruckt. (Denken Sie daran, dass Sie diesen Code in den Quellcode einfügen und C-M-x
zur Auswertung verwenden können. Machen Sie dies dann rückgängig - Sie müssen die bearbeitete Datei nicht speichern.)
Using Debugger
Weitere Informationen finden Sie im Elisp-Handbuch, Knoten .
Rekursion als Schleife
Stellen Sie sich Rekursion jedenfalls als Schleife vor. Es sind zwei Kündigungsfälle definiert: (<= number 0)
und (= number 1)
. In diesen Fällen gibt die Funktion eine einfache Zahl zurück.
Im rekursiven Fall gibt die Funktion die Summe dieser Zahl und das Ergebnis der Funktion mit zurück number - 1
. Eventuell wird die Funktion mit 1
einer Zahl kleiner oder gleich Null aufgerufen .
Das rekursive Fallergebnis lautet daher:
(+ number (+ (1- number) (+ (1- (1- number)) ... 1)
Nimm zum Beispiel (triangle-using-cond 4)
. Lassen Sie uns den endgültigen Ausdruck akkumulieren:
In der ersten Iteration number
folgt 4
also die (> number 1)
Verzweigung. Wir bauen einen Ausdruck auf (+ 4 ...
und rufen die Funktion mit (1- 4)
, dh auf (triangle-using-cond 3)
.
jetzt number
ist 3
und das Ergebnis ist (+ 3 (triangle-using-cond 2))
. Der Gesamtergebnisausdruck ist (+ 4 (+ 3 (triangle-using-cond 2)))
.
number
ist 2
jetzt, so ist der Ausdruck(+ 4 (+ 3 (+ 2 (triangle-using-cond 1))))
number
ist 1
jetzt, und wir nehmen den (= number 1)
Zweig, was zu einer langweiligen 1
. Der ganze Ausdruck ist (+ 4 (+ 3 (+ 2 1)))
. Beurteilen Sie, dass von innen nach außen und Sie bekommen: (+ 4 (+ 3 3))
, (+ 4 6)
, oder einfach nur 10
.
triangle-using-cond
wobei das Argument 1 kleiner ist als die Zahl. Die Bedingungen gehen in der Reihenfolge von a, b und dann c - was zuerst passt, ist, wo der Bock aufhört.