0

I have:

(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))

When I compile opcode-call, REPL outputs:

assigning VAR to ARG
OPCODE-CALL

Why is assign being evaluated at compile time?

Capstone
  • 2,254
  • 2
  • 20
  • 39
  • 2
    Macros are always expanded before compiling, so that the compiled code only includes the expansion. If you don't want your macro to print output during macroexpansion, you need to return the `(format ...)` form instead of evaluating it (put a backquote before it and remove the two you have (which don't do anything at the moment anyway)). – jkiiski May 15 '17 at 08:41

1 Answers1

5

Macros are functions. They take code via their arguments and return new code. Macros can have side effects.

Your code prints something as a side effect during macro expansion and returns NIL (the result of calling the FORMAT function).

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

Using it:

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

It does not make sense to quote the arguments. The code is equivalent to this:

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

It still returns NIL as the expansion, which is probably not what you want.

If you want the macro to expand a form into the call to format, then you need to return that call as a list. Here we use quasiquote to construct a list from a template, filling in two values: name and value.

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

Maybe you want to quote the name:

(defmacro assign (name value)
  `(format t "assigning ~A to ~A~%" ',name ,value))
Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346