0

我有:

(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

为什么在编译时评估分配?

4

1 回答 1

5

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

您的代码在宏扩展期间打印一些副作用并返回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))

它仍然NIL作为扩展返回,这可能不是您想要的。

如果您希望宏将表单扩展为对 的调用format,则需要将该调用作为列表返回。这里我们使用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))
于 2017-05-15T09:00:26.620 回答