Re: Order of macroexpansion
- From: Peter Hildebrandt <peter.hildebrandt@xxxxxxxxx>
- Date: Thu, 31 Jan 2008 20:26:43 +0100
Kent,
thank you for the thorough analysis. c.l.l amazes me anew every time I ask a question. In the beginning I am just after a simple yes or no, and soon I learn things about lisp I would never have thought about.
Kent M Pitman wrote:
It's outer that is reliably expanded first. This follows from an
understanding that eval itself is defined as an operation on an
expression (not a subpart of it) and that operation is described recursively from the outside in:
[snip]
I guessed so, but I did not think of the right terms to look it up. Thanks, this was very enlightening reading.
But if you did not know this, you could mostly have inferred it from
design constraints:
The fact that outer is a macro means a program. Lisp cannot know what
this program will return without running it. Hence, as a consequence,
Lisp cannot know whether inner will still even be in the expansion or,
importantly, whether if it is it will be quoted. In both cases
(omission and quotation), you would not want to run the inner macro.
And, even beyond that, macros take as an argument a representation of
the lexical environment in which they are being expanded [see
&environment], and there is no such environment available until
expansion has been done. Consequently, all of these factors mean that
the design is necessarily such that outer must be expanded to reach
inner.
Again, I had an intuition it should be so, but I failed to come up with a logic argumenmt. Now this is crystal clear.
Is this implementation specific, or can I rely on this?
You can rely on the notion that outer expansion will occur before inner
expansion. However, I would not rely on the other things you're doing here.
And this was the most important part. While I had an intuition that it should work in principal, it left a bad taste. That is why I posted here.
The only thing you can be sure of is that the inner cannot be lexically analyzed until the outer has been executed.
Note well that you cannot be sure that the compiler has not, for
whatever reason, called some other expansion of outer in the interim.
You don't show your calling code here, but for example [2]:
(outer 3 (outer 4 (inner identity)) (inner identity))
will probably have not so good effects for you (assuming I got the uses
of the args right at all).
My actual code is a little more complex than the toy example I posted. The arguments to outer are named, outer uses those names to store interims values in store, which is actually a hash table, and inner takes the names supplied to outer and computes its expansion as a hashtable lookup.
So this would not break my code, but macrolet is really what I want here.
Also, there are cases where the value may surprise you because the
expansion is allowed to be incremental/lazily in non-compiled code
[snip]
Even in compiled code, I can think of various ways in which there are
issues I'd want to think hard about before relying on this strategy,
and I'd say you are leaning too heavily on things not guaranteed to
work for my comfort.
[snip]
Again, thanks for providing this wonderful explanation. I felt what I was doing was not quite kosher, but could not point my finger
at it. This is exactly it. Now I have a good reason to get rid of this ugly hashtable hack.
The correct general shape for a properly cooperative program of the
kind I think you want to write is (I think [2]):
(defmacro outer (val &body body)
(macrolet ((inner (expr) `(,expr ',val)))
,@body))
Yep, that's it. (+ your corrections from your email). This is exactly the way to go.
Again, thank you for your insight!
Peter
.
- References:
- Order of macroexpansion
- From: Peter Hildebrandt
- Re: Order of macroexpansion
- From: Kent M Pitman
- Order of macroexpansion
- Prev by Date: Re: is it true that hash-tables increase their capacity to the next prime number?
- Next by Date: Re: Paul Graham's Arc is released today... what is the long term impact?
- Previous by thread: Re: Order of macroexpansion
- Next by thread: Can I use a docstring followed by DECLARE in a local function?
- Index(es):
Relevant Pages
|
|