为什么在编译函数定义(Clozure Common Lisp)时要评估宏?

Why is a macro being evaluated while compiling a function definition (Clozure Common Lisp)?

我有:

(defmacro assign (name value)
  (format t "assigning ~A to ~A~%" `,name `,value))

(defun opcode-call (&rest args)
  (mapcar (lambda (arg) 
             (if (stringp arg) 
                 (let ((var (gensym)))
                   (assign var arg)
                   var) 
                 arg)) 
          args))

当我编译操作码调用时,REPL 输出:

assigning VAR to ARG
OPCODE-CALL

为什么要在编译时计算赋值?

宏是函数。他们通过参数和 return 新代码获取代码。宏可能有副作用。

您的代码在宏扩展和 returns NIL(调用 FORMAT 函数的结果)期间打印了一些副作用。

(defmacro assign (name value)
  (format t "assigning ~A to ~A~%" `,name `,value))

使用它:

CL-USER 11 > (multiple-value-list (macroexpand '(assign foo bar)))
assigning FOO to BAR      ; prints as a side effect
(NIL T)                   ; the macro expansion returns two values NIL and T

引用参数没有意义。代码等同于:

(defmacro assign (name value)
  (format t "assigning ~A to ~A~%" name value))

它仍然是 returns NIL 作为扩展,这可能不是你想要的。

如果您希望宏将一个表单扩展到对 format 的调用中,那么您需要 return 该调用作为一个列表。这里我们使用 quasiquote 模板 构造一个列表,填充两个值:namevalue.

(defmacro assign (name value)
  `(format t "assigning ~A to ~A~%" ,name ,value))

也许你想引用这个名字:

(defmacro assign (name value)
  `(format t "assigning ~A to ~A~%" ',name ,value))