3

Say I have a macro like

(defmacro repeat (times &body body)
 (let ((x (gensym)))
  `(dotimes (,x ,times)
    ,@body)))

Then I can run on the repl

CL-USER> (repeat 2 (print "Hi"))

"Hi"
"Hi"
NIL

If I run

CL-USER> (list 'print "Hi")
(PRINT "Hi")

So why can't I run

CL-USER> (repeat 2 (list 'print "hi"))
NIL

The backquote just gives me a list doesn't it? Is that not the same as what gets passed to the body parameter when I do not use a backquote (a list of s-expressions)?

Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
Jim
  • 329
  • 1
  • 5

1 Answers1

1

Your code works fine, it just doesn't do what you think it should.

(repeat 2 (print "Hi")) evaluates its second argument twice, so it prints "Hi" two times. It also returns "Hi" twice, but dolist, and, thus, repeat, discards the return value of print.

(repeat 2 (list 'print "hi")) evaluates its second argument twice, so it creates the list (print "hi") twice and discards it. To have it actually print "hi", you would have to evaluate it two times (once producing code (print "hi") the the second time evaluating the code to print "hi").

sds
  • 58,617
  • 29
  • 161
  • 278
  • Thanks for your response sds! Not quite what I was asking but got me on the right track! – Jim Mar 26 '15 at 20:49
  • (let ((mylist (list 'print "Hi"))) (eval `(repeat 2 ,mylist))) – Jim Mar 26 '15 at 20:55
  • 2
    PLEASE see here http://stackoverflow.com/questions/2571401/why-exactly-is-eval-evil regarding eval. You do not need it for this example. – Baggers Mar 27 '15 at 07:41