>>>"MS" == Michael Sperber schrieb am 26 Aug 1998
14:20:32 +0200:
MS> (setq bar 23) (defmacro foo () bar) ; this means (foo) expands to
MS> the value of BAR
Holger> Isn't this meant to mean to refer to the current binding of
Holger> bar, which in this case happens to be 23 ?
MS> What do you mean by "current"? BAR is supposed to refer to the
MS> binding introduced by (setq bar 23), which is the lexically
MS> enclosing one. The question is: when is the binding resolved?
MS> (defun baz () (foo))
MS> This is the crux of the matter: Does the binding get resolved
MS> here?
I tried to look it up (from the HyperSpec on defmacro):
"Defines name as a macro by associating a macro function with that name
in the global environment. The macro function is defined in the same
lexical environment in which the defmacro form appears[1].
The parameter variables in lambda-list are bound to destructured
portions of the macro call.
The expansion function accepts two arguments, a form and an
environment. The expansion function returns a form. The body of the
expansion function is specified by forms. Forms are executed in
order. The value of the last form executed is returned as the
expansion of the macro. The body forms of the expansion function (but
not the lambda-list) are implicitly enclosed in a block whose name is
name."
Footnotes(by me):
[1] So, I would say, that whenever you "call" a macro, you
essentially are calling the macro function which expands the form
given to defmacro, where this is defined in the surrounding lexical
environment. So, when you do
(defmacro foo () bar)
You are calling the macro function in the lexical environment
established for foo. So, now I had to look up, what exactly "lexial
environment" means, in order to see what effects changing bar
afterwards may have:
"lexical environment n. that part of the environment that contains
bindings whose names have lexical scope. A lexical environment
contains, among other things: ordinary bindings of variable names to
values, lexically established bindings of function names to functions,
macros, symbol macros, blocks, tags, and local declarations (see
declare).
lexical scope n. scope that is limited to a spatial or textual region
within the establishing form. ``The names of parameters to a function
normally are lexically scoped.''"
So, it all breaks down to what is the "textual region within the
establishing form" in this case ? It is the top-level form:
"If a defmacro form appears as a top level form, the compiler must
store the macro definition at compile time, so that occurrences of the
macro later on in the file can be expanded correctly. Users must
ensure that the body of the macro can be evaluated at compile time if
it is referenced within the file being compiled."
So, let's compile it ...
USER(10): (compile-file "lisp/defmacro-test")
;;; Compiling file lisp/defmacro-test.lisp
; Compiling FOO
; While compiling (:TOP-LEVEL-FORM "defmacro-test.lisp" 139):
Warning: Free reference to undeclared variable GEE assumed special.
; While compiling (:TOP-LEVEL-FORM "defmacro-test.lisp" 153):
Warning: Free reference to undeclared variable GEE assumed special.
; Compiling FUN
Warning: Free reference to undeclared variable GEE assumed special.
; Compiling BAZ
; While compiling (:TOP-LEVEL-FORM "defmacro-test.lisp" 297):
Warning: Free reference to undeclared variable GEE assumed special.
;;; Writing fasl file lisp/defmacro-test.fasl
Warning: No IN-PACKAGE form seen in lisp/defmacro-test.lisp. (Allegro Presto
will be ineffective when loading a file having no IN-PACKAGE form.)
;;; Fasl write complete
#p"lisp/defmacro-test.fasl"
T
And now, see the difference between interpreted and compiled version:
USER(12): (load "lisp/defmacro-test.lisp")
; Loading lisp/defmacro-test.lisp
gee => 23
(fun) => 23
(baz) => 23
(setq gee 42)
(fun) => 42
(baz) => 42
T
USER(13): USER(13): (load "lisp/defmacro-test")
; Fast loading lisp/defmacro-test.fasl
gee => 23
(fun) => 42
(baz) => 42
(setq gee 42)
(fun) => 42
(baz) => 42
T
So, to sum things up: yes, what I supposed was a rather hackish
solution, which can not be guarenteed to work across CL
implementations nor across interpretation/compilation times.
One last note: have a look at the following quote from CLtL2:
"The defmacro construct arranges to install this expander
function, as the global macro definition of name.
The expander function is effectively defined in the global
environment; lexically scoped entities established outside the
defmacro form that would ordinarily be lexically apparent are not
visible within the body of the expansion function.
X3J13 voted in March 1989 (DEFINING-MACROS-NON-TOP-LEVEL) to clarify
that, while defining forms normally appear at top level, it is
meaningful to place them in non-top-level contexts. Furthermore,
defmacro should define the expander function within the enclosing
lexical environment, not within the global environment."
Holger
--
---
http://www.coling.uni-freiburg.de/~schauer ---
">grep schauer passwd
schauer:x:1075:1075:Holger Schauer,
2790:/home/schauer:/usr/bin/xemacs"
"That's just a shell. LILO booting
/vmunix.el would be really strange."
-- Kristian and Holger in de.comp.os.linux.misc