I want to demonstrate my lack of knowledge with an example.
Using the following two macro defintions,
(defmacro for (var from init to final do &rest body)
"Execute a simple for loop: (for i from 1 to 10 do (print i))."
(let ((tempvar 'max))
`(let ((,var ,init)
(,tempvar ,final))
(while (<= ,var ,tempvar)
,@body
(setq ,var (1+ ,var))))))
(defmacro for (var from init to final do &rest body)
"Execute a simple for loop: (for i from 1 to 10 do (print i))."
(let ((tempvar (make-symbol "max")))
`(let ((,var ,init)
(,tempvar ,final))
(while (<= ,var ,tempvar)
,@body
(setq ,var (1+ ,var))))))
the first macro shadows any variables named max
which may
occur in the body and the second does not, which can be showed with
the following example:
(let ((max 0)) ;; this variable is shadowed if the first macro defintion is used
(for i from 1 to 3 do
(setq square (* i i))
(if (> square max)
(princ (format "\n%d %d" i square)))))
As far as I have learned the evaluation of a macro call works like this:
The macro gets evaluated twice. First the body gets evaluated and returns a form. This form then gets evaluated again.
So far so good.
But if I assume that the macro really returns a chunk of text which happens to be a lisp form, which then gets interpreted, I get a conflict that makes me unable to understand the example above.
What chunk of text does the second macro which uses make-symbol
return,
so that no shadowing occurs? In my understanding an extreme unlikely random choosen
symbol name would make sense.
If I use pp-macroexpand...
both macros return the same expansion.
Is someone able to help me out of this confusion?
print-gensym
andprint-circle
tot
you will be able to see the difference in the macro expansions.#:max
. What does that mean ? I'm highly interested in more details.#:
is just a convention of the printer to indicate an uninterned symbol (this is whatprint-gensym
turns on), there is more detail in the manual:(elisp) Creating Symbols
.