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