有选择地将评估参数传递给宏形式的最佳实践是什么?
详细说明:宏的用处在于它能够接收未评估的参数,这与函数形式的默认评估规则不同。但是,评估宏参数有一个合法的用例。
考虑一个人为的例子:
(defparameter *func-body* '((print i) (+ i 1)))
假设*func-body*可以用作our-defun定义为的宏的主体会很好:
(defmacro our-defun (fun args &body body)
`(defun ,fun ,args ,@body))
所以之后(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可以考虑使用.evaleval
这导致我一开始的问题,有没有更直接或本地的方式来做到这一点?
PS,
一个不太人为的例子是在 function(UPDATE-HOOK)中,它使用两个库宏(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))))))