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-xaby 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-xaby ponownie ocenić definicję.
Korzystanie ze standardowego debugera Emacs
M-x debug-on-entry triangle-using-cond, po triangle-using-conduruchomieniu zostanie umieszczony w debuggerze Emacsa (buforze *Backtrace*).
Przejdź przez ewaluację, używając d(lub cpomiń wszelkie nieciekawe oceny).
Aby zobaczyć stan pośredni (wartości zmiennych itp.), Możesz użyć w edowolnym 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-EVALUATEjest oceniany i wynik jest drukowany. (Pamiętaj, że możesz wstawić taki kod do kodu źródłowego i użyć go C-M-xdo oceny, a następnie cofnąć - nie musisz zapisywać edytowanego pliku).
Aby Using Debuggeruzyskać 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 1liczbą 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 numberjest 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 numberjest 3, a wynik jest (+ 3 (triangle-using-cond 2)). Łączne wyrażenie wyniku to (+ 4 (+ 3 (triangle-using-cond 2))).
numberjest 2teraz, więc wyrażenie jest(+ 4 (+ 3 (+ 2 (triangle-using-cond 1))))
numberjest 1teraz 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-condargumentem 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.