( #sharpsign)是一个标准宏字符,它是一个调度宏字符。它应该与另一个角色组成。( #'sharpsign single-quote)组合后面需要一个函数名或 lambda 表达式,并且它扩展为(function expression).
因此,#'foo在读取时扩展为(function foo). 如果foo是一个函数,function将对它进行评估。在词法范围内,它可能是foo由 aflet或labels绑定的 f 。如果没有这样的词法定义,它将尝试从符号的函数中获取全局函数定义。
现在,在表示宏(function bar)时发出错误信号,无论是词法的还是全局的。但是,您可以使用来获取全局宏的宏功能。如果存在,它是两个参数的函数:表单和环境。barmacroletdefmacro(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,它是特定于实现的。