reddit / emacs

Why does printing in a macro not work?

cuntymccuntlicker · 2022-11-27 01:43
Suppose i have this (defmacro macro-print (i) (print "hello")) (cl-loop for i in '(1 2 3) do (macro-print i)) The output of this is just `hello` followed by nil. Why am I not seeing 3 hello's? I would expect the loop to expand to something like (progn (macro-print 1) (macro-print 2) (macro-print 3)) and then each of these is evaluated in turn, which should each print a hello, where are the other 2 going?
twleo · 2022-11-27 01:47
macro should return a list. ``` (defmacro macro-print (i) '(print "hello")) ``` Note the quote.
KaranasToll · 2022-11-27 01:52
Macros expand to what they return. Your macro prints hello (at macroexpand time) then returns nil or hello (I don't remember; it doesn't really matter). Your macro is only written once, thus is only expanded once. (defmacro macro-print (i) `(print ,i))
[deleted] · 2022-11-27 01:59
[deleted]
cuntymccuntlicker · 2022-11-27 02:22
Ok so this is what I think is going on. I assumed incorrectly that cl-loop expanded to an unrolled loop. It actually expands to a while loop with the macro-print function in the body. Now when the interpreter evaluates the while form, it will evaluate the condition which I assume is true, then it proceeds to evaluating (macro-print i). When it does this, it expands the macro and prints one "hello". Then it evaluates the return value which does nothing. But then in the second and third passes, now that the macro has expanded, there is nothing to evaluate? ​ \*\*EDIT\*\* Perhaps my mental model is incorrect. When the interpreter expands a macro, is it equivalent to calling macroexpand-all? In that case, I can see that when the cl-loop expands, it will also expand (macro-print i), at which point I see the "hello", and leave the return value (another "hello") in its place within the while loop. If this is how it works then I think i got it.
akater · 2022-11-27 09:18
When in doubt, macroexpand: `M-x emacs-lisp-macroexpand`.