宏通常通过调用 来定义。一个 defmacro
看起来很像 defun
。但是与其定义一个函数调用应该产生的值,它定义了该怎么翻译出一个函数调用。举例来说,一个将其参数设为 nil
的宏可以定义成如下:
这定义了一个新的操作符,称为 nil!
,它接受一个参数。一个这样形式 的调用,会在求值或编译前,被翻译成 (setf a nil)
。所以如果我们输入 (nil! x)
至顶层,
要测试一个函数,我们调用它,但要测试一个宏,我们看它的展开式 (expansion)。
函数 macroexpand-1
接受一个宏调用,并产生它的展开式:
理解宏的秘密是理解它们是如何被实现的。在台面底下,它们只是转换成表达式的函数。举例来说,如果你传入这个形式 的表达式给这个函数
它会返回 (setf a nil)
。当你使用 defmacro
,你定义一个类似这样的函数。 macroexpand-1
全部所做的事情是,当它看到一个表达式的 car
是宏时,将表达式传给对应的函数。