Ulrich Hobelmann <firstname.lastname@example.org> wrote:
| Rob Warnock wrote:
| > Marcin 'Qrczak' Kowalczyk <email@example.com> wrote:
| > +---------------
| > | The representation of quasiquotation is not standarized, only its
| > | effect when executed. Different Lisp implementations use different
| > | representations.
| > +---------------
| > Yup. This is one place where Scheme got it right, IMHO, by at least
| > standardizing the name of the quasiquotation macro and the associated
| > internal syntax markers -- QUASIQUOTE, UNQUOTE, and UNQUOTE-SPLICING --
| > that the reader transforms `,,@ into:
| I agree. Do you know in what order Scheme applies quasiquote expansion
| and macro expansion?
As I said in my parallel reply to Eli, basically *all* a Scheme
reader does is change the ` , ,@ readmacros to QUASIQUOTE, UNQUOTE,
and UNQUOTE-SPLICING forms:
mz> (quote `(a ,b ,@(c d) e))
==> (quasiquote (a (unquote b) (unquote-splicing (c d)) e))
It is up to the evaluator which "executes" a QUASIQUOTE form
[effectively a macro call] to create the final list structure:
mz> (let ((b 'foo) (c iota) (d 4))
(quasiquote (a (unquote b) (unquote-splicing (c d)) e)))
==> (a foo 0 1 2 3 e)
| Are there reasons for applying macros last, instead of before
| quasiquote expansion?
QUASIQUOTE *is* just a macro [for all intents & purposes, albeit
R5RS calls it "syntax"], so it's evaluated (as above) in the
ordinary course of events just like any other macro.
| In my case, if the reader, as in Scheme, transformed the punctuation
| merely into Lisp expressions, I could access those inside my macro,
| and the problem would be solved.
Exactly. But in CL, unlike Scheme, "naked" comma and comma-at are
illegal, so you can't.
| In particular, I could use a lone , in the macro's argument, but inside
| the macro it would be find a matching ` . That's what I in fact meant
| with the "dynamic unquote" heading.
This is exactly the property that Scsh relies upon with its
"process-form" macros, e.g.:
(let ((foo "filename")) ; RUN is a Scsh macro that does what
(run (ls -l ,foo))) ; might be called "implicit quasiquoting".
(run (cc ,file ,@flags)) ; Compile FILE with FLAGS.
I have called it "implicit quasiquoting" because the RUN macro behaves
"as if" it were a QUASIQUOTE (plus some other stuff). As you note, the
RUN macro must traverse its arguments "the same as" QUASIQUOTE [or perhaps
build up an explicit QUASIQUOTE form internally and call EVAL].
In CL the backquote must be explicit, so in "CLsh" you'd have to
write it like this:
(let ((foo "filename"))
(run `(ls -l ,foo))) ; Note explicit backquote
(run `(cc ,file ,@flags)) ; (ditto)
| Lisp merely complains, because the reader tries to expand the
| quasiquote and comma first.
To say it another way, in CL the backquote/comma/comma-at readmacros
are defined only in terms of the *final* value after both reading and
evaluation; the intermediate form that the reader returns that EVAL sees
is never explicitly defined in the standard, and may (and *does*!) vary
wildly across implementations (or even *within* an implementation,
depending on the exact input presented to it). Thus the user cannot
depend upon the details of that intermediate form, and the reader can
legally refuse to handle any input that would result in an intermediate
form that the evaluator wouldn't accept -- even if a *user* macro that
consumed that intermediate form might find it quite acceptable!
Conversely, in Scheme the mapping from the reader input readmacros
to intermediate s-expr forms is explicitly defined in R5RS, each in
isolation from the others:
`form <==> (QUASIQUOTE form)
,form <==> (UNQUOTE form)
,@form <==> (UNQUOTE-SPLICING form)
The practical result is that you *can* define macros in Scheme which
"implicitly quasiquote" their arguments, and you *can't* do that in CL
[at least, not in the ANSI standard or any implementation I've tested].
Rob Warnock <firstname.lastname@example.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607