What you're attempting to do with your macro is to expand a literal list.
Macro arguments are not evaluated. So, print-lst
is actually receiving the symbol lst
, not the list bound to the variable.
You either aknowledge that and give print-lst
a literal list, or you may generate code that evaluates the macro argument:
(defmacro print-lst (lst)
(let ((item (gensym)))
;; Macros usually make sure that expanded arguments are
;; evaluated only once and in left-to-right order.
;;
;; In this case, we only have one argument and we only evaluate it once.
`(dolist (,item ,lst)
(print ,item))))
Although, this is obviously not a good example of a macro, it would much better be a function:
(defun print-lst (lst)
(dolist (item lst)
(print item)))
If you wish to inline calls to print-lst
, you may consult your implementation's documentation to see if it pays attention to (declaim (inline print-lst))
.
Another option is to use a compiler macro, in complement to the function, to inline calls where the evaluation of the argument is a known value at compile-time, but again see if your implementation pays any attention to compiler macros:
(define-compiler-macro print-lst (&whole form lst &environment env)
(declare (ignorable env))
;; Some implementations have an eval function that takes an environment.
;; Since that's not standard Common Lisp, we don't use it in constantp.
(if (constantp lst)
`(progn
,@(mapcar #'(lambda (item)
`(print ,item))
(eval lst)))
;; Return the original form to state you didn't transform code.
form))