Re: What's up with Scheme macros?
- From: Kent M Pitman <pitman@xxxxxxxxxxx>
- Date: 20 Feb 2008 09:41:43 -0500
Ron Garret <rNOSPAMon@xxxxxxxxxxx> writes:
In article <uzltwv0t6.fsf@xxxxxxxxxxx>,
Kent M Pitman <pitman@xxxxxxxxxxx> wrote:
[ comp.lang.lisp only; http://www.nhplace.com/kent/PFAQ/cross-posting.html ]
Ron Garret <rNOSPAMon@xxxxxxxxxxx> writes:
I don't understand. Why should:
(let ((x ...))
(defmacro ... () (foo x)))
be any different from:
(let ((x ...))
(defun f () (foo x)))
(defmacro ... () (f ...))
Because the binding has to happen at a known time so the init form
happens at a known time.
Huh?!?
See the discussion of the ''a example below. Note that the semantics you
choose for this needs to be the same that works for other situations--it
can't just support this one example, and not generalize to the language
as a whole.
So, for example, the real issue [and the reason the operator is not
defined this way]
But it IS defined this way! The spec says of 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."
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Because of the restriction you note immediately below here, I think
this means the body of the macro is itself processed in a lexical
environment that sees containing macrolets and symbol-macrolets. I
agree the wording could have been more clear, but I don't know that
the wording can be taken to mean much else by someone charged with
working through the complete set of consequences consistently.
Note that the spec for macrolet says the same thing, but it includes
the following exception, which is NOT part of the spec for defmacro:
"the consequences are undefined if the local macro definitions
reference any local variable or function bindings that are visible
in that lexical environment."
Actually, might be effectively a bug in the spec since it really
cannot work if you reference any block or tag either.
The Lisp1/Lisp2 paper notwithstanding, CL is really a Lisp4 (although
the other two namespaces, block and tag, have so few operations
defined on them that they are rarely mentioned).
is expressed by looking at concrete use cases. A
typical one might be:
When would
(let ((x (print ''a)))
(defmacro foo () x)
(foo))
print (QUOTE A)? At compile time? At load time? Both?
Load time. Why would you doubt it?
Because you can't do the macro expansion without the value of x.
And you can't know the value of x without evaluating the print.
But the value of x is needed at compile time, since you have to
expand foo to compile it. It's even worse if you do:
(progn (print ''b)
(let ((x (print ''a)))
;; Not permitted in CL
(defmacro foo () x)
(foo)))
and ask if you run this interpreted in what order the PRINT would
occur.
(Note that because the defmacro is not a top-level form, the call to
FOO will be compiled as a function call unless FOO has already been
defined as a macro before the file is compiled. And even if FOO has
been previously defined as a macro, the call to FOO will be compiled
as a call to the OLD foo, not the new one.)
Then, at minimum, you won't be able to use FOO as a macro right after
its definition. We thought that would confuse people.
Moreover, why would the compiler know to expand (foo) at all since
the definition of FOO as a macro would not be installed until
runtime, if it were to follow what DEFUN does.
Exactly. I don't see what any of this has to do with anything.
Well, it makes LET be a kind of secret DELAY operator for defmacro.
We thought that would be confusing.
Macros call macroexpansion functions, which can be defined in
lexical environments just like any other function. Macros are
expanded (and hence their macroexpansion functions called) at
compile time, so it is up to the user to insure that those functions
exist at compile time (through appropriate uses of eval-when most
likely). But I don't see any reason why macroexpansion functions
should not be able to close over lexical variables just like any
other function.
Let's be clear. You are wanting a functionality, and are using the
fact that the present semantics doesn't allow the functionality as a
way of claiming that we have argued the semantics is not possible.
The truth is, though, that the problem isn't the semantics per se. A
language is a decision tree full of choice points, where each choice
takes you to a different universe where the particular choice is
taken. The only way to make all possible choices is to have really a
lot of operators (and even then some such universes are nonsensical).
We could have had more kinds of LET. We used to have COMPILER-LET and
didn't like it.
We could have had a kind of this-is-a-LET-but-if-you-put-a-DEFMACRO-
in-it-it-will-morph-secretly-into-COMPILER-LET LET. But we didn't even
try that. That, however, is not a statement that we couldn't have.
At the time, it just didn't seem like a good idea, or not a good enough
idea, or an idea we had time for.
When things happen, they happen for a reason. When things don't,
there can be many reasons, or no reason. So it's risky to posit a
reason for doing something and then claim that the reason something
didn't happen was that someone disagreed with your reason. You might
think the public should invest money in education or in health care or
fixing climate change, and you might think the fact that they don't is
a statement of their belief that such investment won't work. And
there are people who don't think such investment doesn't work. But
there are also people who are just broke or have other things to do.
One further thing we don't want to conclude is that because we want a
particular thing at a particular time, and we're not getting it, we
should just assume it's already there and argue that the semantics of
what's there should just extend to that.
DEFMACRO and LET can only have one semantics at a time. The semantics
you want is different than what is there now. That means at least one
additional operator or language feature, but in any case, one extra
bit of information is needed. To that end, I refer you to
"Pitman's Two-Bit Rule", which I have always intended to cover cases
like this...
http://www.nhplace.com/kent/PS/EQUAL.html#two-bit_rule
.
- Follow-Ups:
- Re: What's up with Scheme macros?
- From: Ron Garret
- Re: What's up with Scheme macros?
- References:
- Re: What's up with Scheme macros?
- From: Kent M Pitman
- Re: What's up with Scheme macros?
- From: Ron Garret
- Re: What's up with Scheme macros?
- Prev by Date: Re: λ notation
- Next by Date: Re: λ notation
- Previous by thread: Re: What's up with Scheme macros?
- Next by thread: Re: What's up with Scheme macros?
- Index(es):
Relevant Pages
|