宏返回代码。由于Lisp中的代码由列表组成,因此可以使用常规列表操作功能来生成它。
;; A pointless macro (defmacro echo (form) (list 'progn (list 'format t "Form: ~a~%" (list 'quote form)) form))
这通常很难阅读,尤其是在较长的宏中。Backquote阅读器宏允许编写通过选择性评估元素填充的引用模板。
(defmacro echo (form) `(progn (format t "Form: ~a~%" ',form) ,form)) (macroexpand '(echo (+ 3 4))) ;=> (PROGN (FORMAT T "Form: ~a~%" '(+ 3 4)) (+ 3 4))
这个版本看起来几乎像常规代码。逗号用于评估FORM; 其他所有内容均按原样返回。请注意,',form单引号位于逗号之外,因此它将返回。
人们还可以,@在位置上拼接列表。
(defmacro echo (&rest forms) `(progn ,@(loop for form in forms collect `(format t "Form: ~a~%" ,form)) ,@forms)) (macroexpand '(echo (+ 3 4) (print "foo") (random 10))) ;=> (PROGN ; (FORMAT T "Form: ~a~%" (+ 3 4)) ; (FORMAT T "Form: ~a~%" (PRINT "foo")) ; (FORMAT T "Form: ~a~%" (RANDOM 10)) ; (+ 3 4) ; (PRINT "foo") ; (RANDOM 10))
反引号也可以在宏外部使用。