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-xzu "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-condWenn triangle-using-condSie 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 eanzeigen. 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-EVALUATEausgewertet und das Ergebnis ausgedruckt. (Denken Sie daran, dass Sie diesen Code in den Quellcode einfügen und C-M-xzur Auswertung verwenden können. Machen Sie dies dann rückgängig - Sie müssen die bearbeitete Datei nicht speichern.)
Using DebuggerWeitere 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 1einer 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 numberfolgt 4also die (> number 1)Verzweigung. Wir bauen einen Ausdruck auf (+ 4 ...und rufen die Funktion mit (1- 4), dh auf (triangle-using-cond 3).
jetzt numberist 3und das Ergebnis ist (+ 3 (triangle-using-cond 2)). Der Gesamtergebnisausdruck ist (+ 4 (+ 3 (triangle-using-cond 2))).
numberist 2jetzt, so ist der Ausdruck(+ 4 (+ 3 (+ 2 (triangle-using-cond 1))))
numberist 1jetzt, 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-condwobei 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.