[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Generalized LET due to RMS
- Subject: Re: Generalized LET due to RMS
- From: Guy.Steele at CMU-10A
- Date: Fri ,29 Aug 80 17:28:00 EDT
I would like to express some support for a generalization of LET
which is due to RMS, I believe. This permits the binding specification
of a LET pair to be any expression constructed from data selectors
(such as CAR, CDR, AREF, and selectors declared by DEFSTRUCT)
*and* data constructors (such as LIST, CONS, and constructors declared
by DEFSTRUCT). Note that a variable name is a kind of middle case halfway
between constructors and selectors.
Thus, for example, one could write:
(LET ((`(,A B ,(CAR C)) (FOO 1 2))) ...)
to mean that the call to FOO is expected to return a 3-list whose
second element is the atom B. The variable A is bound to the first
element and (CAR C) is bound to the third element.
Note that this provides a simple and uniform syntax for binding things other
than variables if one's implementation will support it. One can write
(FUNCTION X) or (FSYMEVAL 'X) to bind the function cell of X;
(GET X 'PROP) to bind the PROP property of the value of X; and so on.
This method, using constructor expressions, is superior to the simple
destructuring versions we have used in the past because it allows
the destructuring and non-variable-binding aspects to be used together.
Also, it allows destructuring of a data object (possibly user defined)
for which there is yet no convenient reader syntax for writing an instance
of the data object itself in the code. Thus instead of
(LET ((#(A B C) ...)) ...)
one writes (LET (((VECTOR A B C) ...)) ...); and if I invent a routine
2X2 which constructs a two-by-two array, I don't need to invent a
reader syntax for such arrays so I can write it in a LET -- I just
write (LET (((2X2 A B C D) ...)) ...). All I need is to set up a little
data base for that constructor name and the appropriate selectors, such
as for SETF. (The means for doing this should be standardized.)
The MULTIPLE-VALUE-BIND construct can be absorbed by LET as a special
case in this new implementation, which is rather flavorful. Suppose
we let VALUES be a function which returns all its arguments:
(DEFUN VALUES (&REST X) (PROG () (RETURN-LIST (APPEND X '()))))
then one needn't use the crufty PROG syntax for returning multiple values:
(DEFUN FOO (A B)
(VALUES (CAR A) (HACK B) (LIST B)))
The function FOO returns three values. Then I can call FOO and save
the three values by writing:
(LET (((VALUES X Y Z) (FOO P Q))) ...)
getting the three values in X, Y, and Z.
For the theoretically minded, I can't help noting how reminiscent
this scheme is to the operation of resolution.