( #
sharpsign)是一个标准宏字符,它是一个调度宏字符。它应该与另一个角色组成。( #'
sharpsign single-quote)组合后面需要一个函数名或 lambda 表达式,并且它扩展为(function expression)
.
因此,#'foo
在读取时扩展为(function foo)
. 如果foo
是一个函数,function
将对它进行评估。在词法范围内,它可能是foo
由 aflet
或labels
绑定的 f 。如果没有这样的词法定义,它将尝试从符号的函数中获取全局函数定义。
现在,在表示宏(function bar)
时发出错误信号,无论是词法的还是全局的。但是,您可以使用来获取全局宏的宏功能。如果存在,它是两个参数的函数:表单和环境。bar
macrolet
defmacro
(macro-function 'bar)
bar
除非您要将bar
's 宏功能应用于表单,否则它可能不是您想要的。让我们考虑应用 的宏功能and
:它不会进行逻辑布尔运算,它可能会将给定的形式扩展为if
.
但是,如果这是您想要的,请记住它macro-function
还有第二个可选参数,即环境。defmacro
您可能会在 a或 a中获得一个环境作为参数define-setf-expander
。在后者中,通常需要它以便get-setf-expansion
在扩展子表单时考虑词汇环境。
试试这个:
(funcall (macro-function 'and) '(and form1 form2 form3) nil)
练习:实现你自己的macroexpand-1
和macroexpand
.
练习:实现 a macroexpand-all
, amacroexpand
递归到子表单中,识别 Common Lisp 的特殊运算符。
注意:不要走得太远macroexpand-all
,它需要一个代码walker,它是特定于实现的。