デバッグ

テキスト『これが LISP だ!』の 4.4.1(p.66)にある, 関数 pair-off およびその補助関数を 例に,バックトレースによるデバッグの方法を説明します. プログラムの開き方 および プログラムのロード方法は知っているものとします.

関数の定義

最初に,関数 pair-off およびその補助関数を,テキストにしたがって 定義します.テキストでは関数を直接に入力していますが, 関数定義を書いたファイルを作成して保存し,それをロードすることにします. その方がプログラムの編集が容易です. このプログラム(bugfix.lisp)を用意しましたので,以下のリンクから ダウンロードしてください. テキストでは second という補助関数を定義していますが, CLISP ではこの関数はすでに定義されています. そこで,my-second という関数名を使いました.

関数 pair-off およびその補助関数の定義(bugfix.lisp)

ダウンロードしたプログラムは,適当な場所(たとえば, ~/lisp/anderson/chap4/ の下)においてください.

Emacs のウィンドウが2分割され,下のウィンドウで CLISP が走っている とします.上側のウィンドウで bugfix.lisp を開いてください. 上側のウィンドウにカーソルがあるのを確認してから, C-x C-f で bugfix.lisp を開きます.

open bugfix.lisp

ファイル bugfix.lisp が開かれ, 上側のウィンドウに関数定義が示されます.

open bugfix.lisp

下側のウィンドウにカーソルを移動してから,bugfix.lisp を ロードします.

load bugfix.lisp

エラーから抜ける

リスト (a b c d) を引数にして,pair-off 関数を呼び出してください. 下側のウィンドウで (pair-off '(a b c d)) と入力して, Enter キーを押せばよいでしょう. ((a d) (b c)) というリストが返されればよいのですが...

CAR: A is not a list というエラーメッセージが表示され, ブレークループ状態に入りました. このエラーメッセージは,a を引数にして car が呼び出されたと 言っています.car の引数はリストでなければなりませんから, エラーになったのです.

error: A is not a lisp

ブレークループから抜けるには,:q と入力して Enter キーを 押します.

quit :q

バックトレース

pair-off およびその補助関数の定義は簡単で,car は3か所で 使われているだけですから,どこでエラーが生じたのか 特定することはそんなに難しくありません. しかし,関数定義が少し複雑になると,エラーの原因個所の特定は かなりやっかいになることがよくあります.

このようなとき,バックトレースを使うと,エラー箇所の特定に 役立ちます. もう一度 (pair-off '(a b c d)) と入力してください.

ブレークループで :bt と入力して Enter キーを押してください. テキスト p.67 では (backtrace) という関数を呼び出しています. :bt コマンドはこれと同じです.

backtrace :bt

テキストで説明されているように,バックトレースは LISP が行った処理の一覧が表示されます.行われた処理の順序は, この一覧の下から上です.すなわち,EVAL frame for form (pair-off '(a b c d)) が最初です.これは (pair-off '(a b c d)) が 評価されたという意味です.

backtrace: EVAL (pair-off '(a b c d))

処理の一覧を上にたどっていくと,pair-off 関数の定義にある (LIST (OUTER-PAIR LIS) (INNER-PAIR LIS)) が評価され, さらに (INNER-PAIR LIS) が評価されていることがわかります.

最後に,(my-second y) が評価され,仮引数 y を '(a b c d) として, 関数 my-second の実行が試みられました.さらに, my-second の実行で,(car (car z)) が評価されています. ここでエラーが生じたのです.

backtrace: EVAL (pair-off '(a b c d))

ブレークループの中では仮引数に何が代入されたかを 調べることができます.(car (car z)) の z に代入された ものを調べるために,z と入力して Enter キーを押してください. (a b c d) というリストが表示されます.これが z に代入されたものです.

backtrace: argument z