glider-gun's Blog

何か書きます

Debugging Lisp Part 2: インスペクト

このエントリーは、著者の許可をいただいて http://malisper.me/category/debugging-common-lisp/ のCommon Lispのデバッグに関する連載を翻訳するものです。

目次: 第1回 第2回 第3回 第4回 第5回


このエントリーは連載 Debugging Lispの第2回です。第1回はこちら

このエントリーではCommon Lispのもう一つのデバッグツール、Slimeのインスペクタについて議論します。 Slimeインスペクタは、オブジェクトをreplから直接操作することを可能にします。 色々なことができ、例えばオブジェクトをクリックして内容をみることもできますし、オブジェクトをコピーアンドペーストして後の関数呼び出しで使うこともできます1。 次のようなpointクラスがあるとしましょう:

1
2
3
(defclass point ()
  ((x :accessor point-x :initarg :x :initform 0)
   (y :accessor point-y :initarg :y :initform 0)))

このクラスのインスタンスを作るには次のようにします:

1
(make-instance 'point :x 10 :y 20)

返されたオブジェクトを右クリックして"inspect"オプションを選ぶか、emacsのショートカット"C-v C-v TAB"を使うことでオブジェクトの中をのぞくことができます:

全てのインスタンス変数の現在の値が表示されます。表示するだけでなく、変数の値を変更することも出来ます。これらがデバッガ内から、実行時に使えることが強力なのだということに注意してください。

実際にオブジェクトの値が変更されたことを確認するには、このオブジェクトをコピーアンドペーストし、 point-x 関数に与えて呼び出すことができます。

インスペクタに関してもう一つとてもクールなのは、Slimeのトレースダイアログです。トレースダイアログは普通のトレースに似ていますが、トレースされている関数が渡されたり返すオブジェクトがインスペクトできるようになっています。例えば、あなたが次のような末尾再帰最適化された関数 sum を書いているとしましょう。これはリストの中の全ての数を足し合わせます。

1
2
3
4
5
6
7
(defun sum (xs &optional (acc 0))
  (if (null xs)
      acc
      (sum (cdr xs) (+ (car xs) acc))))
 
(sum '(1 2 3))
=> 6

関数 sum をトレースするかどうかは、ショートカット “C-c M-t” の後、関数の名前 “sum” を打つことで切り替えることができます。関数をトレースした後、"C-c T"でインタラクティブなトレースダイアログのバッファに入れます。"G"を押すことで情報を更新して一番最後のトレースを得ることができます。

このトレースは普通のトレースと大体同じ見た目をしていますが、よい機能があります。上で述べたように、関数の全ての引数と返り値をインスペクトすることができるのです。見やすいようにトレースの枝の表示/非表示を切り替えることも出来ます。

Slimeのトレースダイアログは、コードが多数のオブジェクトをやりとりしていて、自分がその中身について確信が持てないときに非常に有用です。これを使うだけであなたに必要な情報の全てを追ってくれるのです。

SlimeのインスペクタはCommon Lispのデバッグツール群のもう一つの素晴らしい機能です。プログラムがクラッシュし、原因が分からないときに重宝します。他のデバッグツール群と組み合わされば最高です。

原文: http://malisper.me/2015/07/14/debugging-lisp-part-2-inspecting/


  1. 技術的にはこれはインスペクタの機能ではなく"Presentation"の機能です。インスペクタはオブジェクトの中を見る機能にあたります。

Comments