mck*_*mck 3 macros common-lisp splice
让我们假设:
(defmacro testing (&optional var)
`(list 'this 'is
,@(when (consp var) `('a 'list))))
Run Code Online (Sandbox Code Playgroud)
调用时:
>(testing 2)
(THIS IS)
>(testing (list 1 2))
(THIS IS A LIST)
Run Code Online (Sandbox Code Playgroud)
这就是我想要的。但是现在,当我传递一个列表参数时:
>(defparameter bla (list 1 2 3))
BLA
>(testing bla)
(THIS IS)
Run Code Online (Sandbox Code Playgroud)
我想这是因为宏会检查(consp bla)bla 在哪里是符号,而不是列表?我如何防止这种情况?
谢谢
你可以这样做:
(defmacro testing (&optional var)
`(if (consp ,var)
'(this is a list)
'(this is)))
Run Code Online (Sandbox Code Playgroud)
所以var将在运行时(不是编译时)进行评估。var在宏的扩展中只出现一次,但如果出现不止一次,则必须使用 gensym。
编辑:如果您不想输入'(this is)两次,请执行以下操作:
(defmacro testing (&optional var)
`(append '(this is) (when (consp ,var) '(a list))))
Run Code Online (Sandbox Code Playgroud)
不要使用eval,它很慢,而且完全没有必要。通过代var入宏展开,自然会在运行时求值。如果您使用 eval,您将执行以下操作:
(eval (append '(list 'this 'is) (when (consp 'bla) '('a 'list))))
Run Code Online (Sandbox Code Playgroud)
每次执行时,它都会建立一个代表代码的列表并在运行之前编译它。(希望这不是在循环中!)如果您只使用生成简单代码(没有eval)的宏,它只会编译一次。