You wrote you know that the correct form to define this macro would have been:
(defmacro macro-print (s)
`(print "hello"))
If you now do:
(dotimes (i 3)
(macro-print i))
it correctly prints 3 times "hello"
and returns nil
.
(You should prefer in such cases dotimes
instead of the let-while-setq
construct, since for such side-effect loops do-
loops should be preferred - and are more readable).
I think, what exactly happens will be clearer, when you try
(defmacro macro-print (s)
`(print "hello"))
(macroexpand-1 '(macro-print 1))
;; => (print "hello")
But with your:
(defmacro macro-print (s)
(print "hello"))
(macroexpand-1 '(macro-print 1))
;; "hello" ;; while expanding, `(print "hello")` gets executed
;; => "hello" ;; this macro expands to the return value
;; ;; of (print "hello") executed during
;; ;; the macroexpansion!
So while the former version of (macro-print <something>)
expands to the code snippet (print "hello")
,
the latter version (which you used!) of (macro-print <something>)
expands to a simple litral string "hello"
.
So, in your example, if you do
(dotimes (i 3)
(macro-print i))
This expands to
(dotimes (i 3)
(print "hello"))
Which gives the desired behavior (printing 3x "hello" on the stdoutput),
- but your actual example expands to:
(dotimes (i 3)
"hello")
Which of course doesn't print anything to stdout (the screen).
The only time it prints something to the screen is,
when the macro gets expanded once.
Hence just one "hello"
one the screen.
So your mistake in thinking was that you thought
your macro expands to (print "hello")
while it actually
merely expands to "hello"
- therefore NOT seeing
3x a "hello" on the screen is totally to be expected!
And another thing:
The "hello"
on your screen was printed not during execution time but during expansion time of your code,
so it was not printed while the loop was being executed, but before that.
While - with the correct definition of the macro - nothing
is printed on the screen during expansion of the macro,
but during the loop being executed, the "hello" gets printed on the screen 3x as expected.
When dealing with macro's always check with macroexpand-1
This gives you one basic rule for macro programming in Lisp:
Always use macroexpand-1
whenever you define a macro - to understand what the macro actually expands to!