自定义宏的语法为:
(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) |
本文深入探讨了自定义宏的语法及其工作原理,通过实例解释了宏如何通过参数列表、文档字符串和body部分进行定义。进一步解析了宏参数的使用方式,包括&rest和&body的等价性,以及backquotedexpression的作用,特别是在处理宏参数时如何避免意外的行为。
2732

被折叠的 条评论
为什么被折叠?



