[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
- To: dlw at MIT-AI
- From: Guy.Steele at CMU-10A
- Date: 29 September 1980 1646-EDT (Monday)
Subject: Macros and destructuring and...
CC: bug-lsip at MIT-MC, bug-lispm at MIT-MC, macsyma-i at MIT-MC
Message-Id: <29Sep80 164658 GS70@CMU-10A>
From: Daniel L. Weinreb <DLW at MIT-AI>
From: Guy.Steele at CMU-10A
Sorry, Dan, I beg to differ with you on the philosophical nature of macros.
Macros certainly are functions, of one argument.
No, I still don't agree. A macro is implemented as a function of one
argument in the meta-language. From the point of view of the
meta-language it is a function of one argument. But functions in the
meta-language have nothing to do with functions in the language; from
the point of view of the language, a macro is a translator and not a
What you say here is correct, but ignores the crucial point that LISP
IS ITS OWN META-LANGUAGE. In a language like BLISS, it is perfectly
reasonable for procedure syntax and macro syntax to be different.
In LISP, they ought to be similar because what is a meta-function at
one time is simply a function at another. What's sauce for the goose
is sauce for the gander: if destructuring is good for macros, then
also for functions. And the point about utility functions used by macros
drives this home.
Now, the fact
that macros and functions are invoked by means of the "same syntax"
is sort of a coincidence, and not at all essential.
Yes. That's what I said, too. I don't see why you are debating this.
I went on to say that this coincidence should not fool you into
thinking that lambda lists and defmacro patterns are "the same thing".
That's right: *this* coincidence shouldn't fool you, but the coincidence
of language and meta-language *should* fool you.
Now, it is true that in practice up until now destructuring has been the most
useful for macros, which commonly parse apart their arguments into known
fixed pieces. There is also the fact that ordinary functions in effect
already get one level of destructuring by the fact that they are
considered to get many named arguments rather than a single one (which
is usually a "vector" of some sort); but after all, what are &OPTIONAL
and &REST but destructuring mechanisms? There is something to be said
for unifying that mechanism with the one used by DEFMACRO and the NIL LET,
provided it can be done without undue clutter.
No, I do not buy this argument at all. &OPTIONAL and &REST are not
"destructuring an argument vector". Functions are not passed an
argument vector; they are passed several arguments. &OPTIONAL has
absolutely nothing to do with destructuring; you might think &REST
does, but I don't; the only reason that list is there is because it is
the easiest way to let you deal with an unanticipatable number of
arguments. That list got CONSed; it did n't "fail to get
Actually, what I meant is that when you *don't* specify &REST right off
the bat you are getting destructuring by default, and have to say &REST
to avoid it!
But actually, I was indeed thinking that functions *are* passed an
argument vector--on the stack, typically--but this kind of vector
is not made an explicit LISP data type so that the implementation is
free to handle them efficiently. And see the fact that the &REST
argument mechanism gets you a CDR-coded list on the LISP Machine,
but a LISP vector data type in NIL; this is a reflection of the
underlying efficient mechanisms.
RMS has noted that if you had a VALUES construct for returning
multiple values [such as (LAMBDA (X) (VALUES (CAR X) (HACK X) T))
which returns three things], and also adopted the policy that
destructuring be guided by constructor functions [such as
(LET ((`(,a ,b . ,c))) ...)], then one gets multiple-value-bind
as a special case: (LET (((VALUES A B C) (FOO X))) ...).
Applying the observation that function call and function return
are similar operations (obvious when you consider continuations,
or the MULTIPLE-VALUE-BIND syntax), one concludes that the
argument vector to a function may also be modeled by the VALUES
construct--it is an "internal vector of values". So destructuring
makes sense there too.
Therefore I believe that an effort should be made to specify a simple,
consistent syntax which encompasses function entry, function return, optionals,
macros, destructuring, and binding of non-variables (such as function
cells or cars of lists) which can be used in DEFUN, DEFMACRO, LET,
and SETF. I also believe that this facility should probably
be used sparingly in many cases.