評価された引数をマクロ フォームに選択的に渡すためのベスト プラクティスは何ですか?
詳しく説明すると、マクロの有用性は、関数形式のデフォルトの評価規則とは異なり、未評価のパラメーターを受け取る機能にあります。ただし、マクロ引数を評価する正当な使用例があります。
不自然な例を考えてみましょう:
(defparameter *func-body* '((print i) (+ i 1)))
次のように定義され*func-body*
たマクロの本体として機能できると便利だとします。our-defun
(defmacro our-defun (fun args &body body)
`(defun ,fun ,args ,@body))
したがって、 の後に、 get(our-defun foo (i) (+ 1 i))
と言うことができます。ただし、 を使用すると、 の結果は(つまり、 の値) になります。マクロの引数としての評価を強制できるとよいでしょう。(foo 1)
2
(our-defun foo (i) *func-body*)
(foo 1)
((PRINT I) (+ I 1))
*func-body*
*func-body*
our-defun
現在、次のように、これを使用compile
および実行する手法を考えることができます。funcall
(funcall (compile nil `(lambda () (our-defun foo (i) ,@*func-body*))))
その後、意図したとおり、(our-defun 1)
1 を出力して を返します。2
これを で動作させるケースも考えられますが、スコーピングの特殊性eval
から避けたいと思います。eval
これは最初に私の質問につながります.これを行うためのより簡単な方法またはネイティブな方法はありますか?
PS、
あまり工夫されていない例が function(UPDATE-HOOK)
にあります。これは 2 つのライブラリ マクロを使用し(ADD-HOOK)
、(REMOVE-HOOK)
そのパラメータを評価する必要があります。ここでは、上記の(funcall (compile nil `(lambda () ...)))
手法が使用されます。
(defun update-hook (hook hook-name &optional code)
(funcall (compile nil `(lambda () (remove-hook ,hook ',hook-name))))
(unless (null code)
(compile hook-name `(lambda () ,@code))
(funcall (compile nil `(lambda () (add-hook ,hook ',hook-name))))))