プログラムの途中で発生する問題点を調べるための1つの有用な技法は、 ある関数を呼び出すたびにデバッガに入ることです。 問題を生じる関数に対してこのようにしておき、 当該関数をステップ実行するか、あるいは、 問題が発生する直前に呼ばれる関数に対してこのようにしておき、 その関数の呼び出しを終えてから、呼び出し側をステップ実行します。
この関数は、function-nameが呼び出されるたびに デバッガを起動するようにする。 当該関数の定義の最初のフォームとして フォーム
(debug 'debug)
を挿入することでこれを行う。Lispコードで定義した任意の関数は、 解釈実行コードであろうとコンパイル済みのコードであろうと、 関数に入るときにブレークするようにできる。 関数がコマンドであると、Lispから呼ばれたときや 対話的に呼ばれたときに(引数を読み取ってから)デバッガに入る。 (Cで書いた)基本関数は、この方法ではデバッグできない。
debug-on-entry
を対話的に呼び出すと、 ミニバッファでfunction-nameを問い合わせる。 その関数がすでに呼び出し時にデバッガを起動するようになっていると、debug-on-entry
はなにもしない。debug-on-entry
はつねにfunction-nameを返す。注意:
debug-on-entry
を使ったあとに当該関数を再定義すると、 デバッガに入るためのコードがなくなる。 実質的には、関数を再定義すると呼び出し時にブレークする機能を 取り消すことになる。(defun fact (n) (if (zerop n) 1 (* n (fact (1- n))))) ⇒ fact (debug-on-entry 'fact) ⇒ fact (fact 3) ------ Buffer: *Backtrace* ------ Entering: * fact(3) eval-region(4870 4878 t) byte-code("...") eval-last-sexp(nil) (let ...) eval-insert-last-sexp(nil) * call-interactively(eval-insert-last-sexp) ------ Buffer: *Backtrace* ------ (symbol-function 'fact) ⇒ (lambda (n) (debug (quote debug)) (if (zerop n) 1 (* n (fact (1- n)))))