I have recently learned (in shock!) that it is impossible to
predict the moment a macro defined via defmacro
is
expanded (i.e., its code is run in order to generate the expanded
form which will in turn run when the macro is invoked). For
instance, when you run the macro
(defmacro report-case-fold-search ()
`(message "case-fold-search is currently %s" ,case-fold-search))
there is no way to predict the output since it depends on the
value of case-fold-search
at the moment the macro was expanded
and you cannot predict that!
After swallowing that information (a bit reluctantly), out of
sheer curiosity I started to experiment with it trying to
understend how it all works. The first question that comes to
mind is this: OK, if a macro is expanded ahead of time, how can
it possibly know in advance what the values of its parameters
are? I explain: suppose the expansion of a macro depends both on case-fold-search
and on a
parameter p
such as
(defmacro report-case-fold-search-and-parameter (p)
`(message "case-fold-search is currently %s and the parameter given is %s" ,case-fold-search ,p))
(notice that the last occurence of p
is evaluated, so the macro
needs to know the value of p
in order to be
expanded).
When I run it with various values of case-fold-search
and p
,
I notice that any change in p
is immediately reflected in the
output, but changes in case-fold-search
are not.
To see for yourself try repeatedly running the following in random order:
(progn
(setq case-fold-search t)
(report-case-fold-search-and-parameter 1))
(progn
(setq case-fold-search t)
(report-case-fold-search-and-parameter 2))
(progn
(setq case-fold-search nil)
(report-case-fold-search-and-parameter 1))
(progn
(setq case-fold-search nil)
(report-case-fold-search-and-parameter 2))
This shows that at least part of the work leading to the
expansion of this macro is taking place after the parameter p
is provided, hence at run-time. However, this late expansion is
not updating the value of case-fold-search
or at least not
doing it immediately.
Even though I was previously frowned upon for asking about the
time a macro expansion takes place, I'd like to know what is
going on? In the last part of the macro definition above, namely around
,case-fold-search ,p))
, can it possibly be that the evaluation of case-fold-search
takes
place before the macro is invoked, while the evaluation of p
is
done afterwards? To put it another way, it looks like the
evaluation of the form
`(message "case-fold-search is currently %s and the parameter given is %s" ,case-fold-search ,p))
is partially performed at some earlier time and then concluded
after the value of p
is known. Is that right?