自定义宏的语法为:
(defmacro name (parameter*)
"Optional documentation string."
body-form*)
如一个函数样,宏由一个宏名字,一个参数列表,一个可选文档字符串和一个body组成。
Macro Parameters
在定义宏的参数时,也可以加&rest parameter,用于让宏接受不定数量的参数。同时也可以用&body来代替&rest,它们是等价的。
Generating the Expansion
先看个例子:
(defmacro print-x (x) (format t "~d~%" x))
(print-x (+ 1 1))
上述代买被执行后,输出的结果为(+ 1 1),而不是2,这是为什么呢?个人的理解是,宏PRINT-X被展开时,其body中的x被宏参数的quoted表达式直接代替,而不是用该宏参数的值来代替x造成的。
当需要宏参数的值来替代宏body中的参数,则可以使用backquoted expression。backquoted expression(反引号表达式)与quoted表达式类似,但是它允许其中包含的前有逗号的子表达式作"unquote"操作。有时还可能是逗号后再跟上'@'符号。它们的区别是:
当有@符号时,要被做“unquote”的子表达式的值必须是一个list,并且在对backquoted表达式求值时这个list会被展开;
当无@符号时,直接把前有逗号的子表达式的值来替换该子表达式。
Backquote Examples:
Backquote Syntax | Equivalent List-Building Code | Result |
`(a (+ 1 2) c) | (list 'a '(+ 1 2) 'c) | (A (+ 1 2) C) |
`(a ,(+ 1 2) c) | (list 'a (+ 1 2) 'c) | (A 3 C) |
`(a (list 1 2) c) | (list 'a '(list 1 2) 'c) | (A (LIST 1 2) C) |
`(a ,(list 1 2) c) | (list 'a (list 1 2) 'c) | (A (1 2) C) |
`(a ,@(list 1 2) c) | (append (list 'a) (list 1 2) (list 'c)) | (A 1 2 C) |