2017-07-02 13 views
0

traceマクロはデバッグに非常に便利です。しかし、どのマクロでも使用されると停止する。同様に私は次の操作を行いますしようとした場合:マクロとトレース方法

CL-USER> (trace push) 

その後、それはというエラーをあげる:traceのclhsページは、明らかに機能すると、それを定義するため

can't use encapsulation to trace anonymous function #<FUNCTION (MACRO-FUNCTION 
                   PUSH) {100053FB9B}> 
    [Condition of type SIMPLE-ERROR] 

まあ、それは明らかです。ですから、Common Lispでマクロをトレースする機能を持たない理由は何ですか?
Common Lispでマクロをトレースする方法は他にもありますか?

+1

マクロがコンパイル時に展開された場合、それらの呼び出しをどのようにトレースするのでしょうか?展開されたマクロの最初の形式を選択し、その上に 'trace'を呼び出したマクロを書くことができます。 – Carcigenicate

+1

どのような状況でマクロをトレースしますか? SBCLでは、非標準の ':ENCAPSULATE'引数を使用してトレースすることが可能です:'(trace push:encapsulate nil) '。通常、マクロ展開(macroexpanding)はマクロをデバッグするより良い方法です(Slyではマクロステップも使用できます)。マクロ内の複雑なロジックは、通常はトレースすることができる別の関数で実装することもできます。 – jkiiski

+0

ありがとう@jkiiski!組み込みマクロのマクロ展開( 'push'のような)は、プログラムで実際に何が行われたのかを知る必要がある時代にはあまり役に立ちません。 – Mooncrater

答えて

4

Common Lisp標準には、関数のトレースが記載されています。

しかし、いくつかのCommon Lispの実装は、マクロをトレースすることができます

CLISPはマクロをトレースすることができます

[1]> (defmacro foo (a) a) 
FOO 
[2]> (trace foo) 
;; Tracing macro FOO. 
(FOO) 
[3]> (loop for i below 4 collect (foo i)) 
1. Trace: (FOO I) 
1. Trace: FOO ==> I 
1. Trace: (FOO I) 
1. Trace: FOO ==> I 
1. Trace: (FOO I) 
1. Trace: FOO ==> I 
1. Trace: (FOO I) 
1. Trace: FOO ==> I 
(0 1 2 3) 

LispWorksは、マクロのトレースをサポートする別の実装です。

だから、Common Lispでマクロをトレースする機能がないのはなぜですか?

言われたように、言語基準です。言語以外の標準実装では、マクロをトレースするためのいくつかのLispインタプリタ(!)の機能を含む、さまざまな方法であらゆる種類の言語拡張を提供しています。

コードが既にコンパイルされていると、トレースはとにかく動作しません。 Lispインタプリタがあれば助けますが、実装にはインタプリタを必要としません。ここでのLispインタプリタとは、Lispコードからデータとして動作する実行エンジンを意味します。マクロにtraceを使用して

2

は少し奇妙に思えるが、それはCLISPで動作します。

(trace push) 
(defparameter *stack* '()) 

(defun push-xy (x y) 
    (push x *stack*) 
    (push y *stack*)) 
; 1. Trace: (push x *stack*) 
; 1. Trace: push ==> (setq *stack* (cons x *stack*)) 
; 1. Trace: (push y *stack*) 
; 1. Trace: push ==> (setq *stack* (cons y *stack*)) 
; ==> push-xy 

機能とラムダが定義されている場合、これは起こるかもしれないので、それはマクロを展開する必要がある場合、標準は言っていません、コンパイルされ、時々呼び出される。いくつかの実装ではマクロを2回実行するので、出力が2倍になります。

これは決して使用しません。私はむしろmacroexpand-1を使用します。フォームは、マクロを使用する新しいフォームを返す

(macroexpand-1 '(push x *stack))) 
; ==> (setq *stack (cons x *stack)) 
; ==> t 

場合は、代わりにmacroexpandをしようとする場合があります。そのような変革が残るまでmacroexpand-1を何度も呼び出すように。

関連する問題