Korzystanie z „debugowania printf”
Możesz pozwolić Emacsowi pomóc w zrozumieniu, modyfikując definicję funkcji:
(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))))))
Po prostu dodaj (message ...)
gdzieś, aby wydrukować ślad do *Messages*
bufora.
Korzystanie z Edebug
Umieść punkt w dowolnym miejscu definicji funkcji i wciśnij, C-u C-M-x
aby ją „instrumentować”. Następnie oceń funkcję, np. Umieszczając punkt po (triangle-using-cond 3)
i naciskając C-x C-e
.
Jesteś teraz w trybie Edebug. Naciśnij spację, aby przejść przez funkcję. Wartości pośrednie każdego wyrażenia są pokazane w obszarze echa. Aby wyjść z trybu Edebug, wystarczy nacisnąć q
. Aby usunąć oprzyrządowanie, umieść punkt w dowolnym miejscu definicji i naciśnij, C-M-x
aby ponownie ocenić definicję.
Korzystanie ze standardowego debugera Emacs
M-x debug-on-entry triangle-using-cond
, po triangle-using-cond
uruchomieniu zostanie umieszczony w debuggerze Emacsa (buforze *Backtrace*
).
Przejdź przez ewaluację, używając d
(lub c
pomiń wszelkie nieciekawe oceny).
Aby zobaczyć stan pośredni (wartości zmiennych itp.), Możesz użyć w e
dowolnym momencie. Zostaniesz poproszony o wprowadzenie sexp w celu oceny, a wynik oceny zostanie wydrukowany.
Podczas korzystania z debugera trzymaj kopię kodu źródłowego widoczną w innej ramce, abyś mógł śledzić, co się dzieje.
Możesz także wstawić jawne wywołania, aby wprowadzić debugger (mniej lub bardziej punkty przerwania) w dowolnych miejscach w kodzie źródłowym. Wstawiasz (debug)
lub (debug nil SOME-SEXP-TO-EVALUATE)
. W tym drugim przypadku, po wprowadzeniu debuggera SOME-SEXP-TO-EVALUATE
jest oceniany i wynik jest drukowany. (Pamiętaj, że możesz wstawić taki kod do kodu źródłowego i użyć go C-M-x
do oceny, a następnie cofnąć - nie musisz zapisywać edytowanego pliku).
Aby Using Debugger
uzyskać więcej informacji, zobacz instrukcję Elisp, węzeł .
Rekurencja jako pętla
W każdym razie pomyśl o rekurencji jako o pętli. Zdefiniowano dwa przypadki zakończenia: (<= number 0)
i (= number 1)
. W takich przypadkach funkcja zwraca liczbę prostą.
W przypadku rekurencyjnym funkcja zwraca sumę tej liczby i wynik funkcji za pomocą number - 1
. Ostatecznie funkcja zostanie wywołana z 1
liczbą lub liczbą mniejszą lub równą zero.
Wynik przypadku rekurencyjnego jest zatem następujący:
(+ number (+ (1- number) (+ (1- (1- number)) ... 1)
Weźmy na przykład (triangle-using-cond 4)
. Skumulujmy końcowe wyrażenie:
w pierwszej iteracji number
jest 4
, więc (> number 1)
gałąź jest śledzona. Zaczynamy budować wyrażenie (+ 4 ...
i wywołujemy funkcję za pomocą (1- 4)
, tj (triangle-using-cond 3)
.
teraz number
jest 3
, a wynik jest (+ 3 (triangle-using-cond 2))
. Łączne wyrażenie wyniku to (+ 4 (+ 3 (triangle-using-cond 2)))
.
number
jest 2
teraz, więc wyrażenie jest(+ 4 (+ 3 (+ 2 (triangle-using-cond 1))))
number
jest 1
teraz i bierzemy (= number 1)
gałąź, co powoduje nudę 1
. Całe wyrażenie brzmi (+ 4 (+ 3 (+ 2 1)))
. Ocenia, że od wewnątrz na zewnątrz i masz: (+ 4 (+ 3 3))
, (+ 4 6)
lub po prostu 10
.
triangle-using-cond
argumentem jest 1 mniej niż dowolna liczba. Warunki są uporządkowane w kolejności a, b, a następnie c - niezależnie od tego, co pasuje najpierw, kończy się buck.