Saturday Feb 07,1981 NM+3D.15H.34M.49S. LISP 2071 / COMPLR 1094 -- JonL --
1) Multiple-value capability implemented thru some autoloadable things:
New AUTOLOADable macros and capabilities from MLMAC:
MULTIPLE-VALUE, VALUES, MULTIPLE-VALUE-BIND
Autoloading SUBRs from file MLSUB:
MULTIPLE-VALUE-LIST, VALUES-LIST, and SI:CHECK-MULTIPLICITIES
Non-autoloading macros available in MLMAC:
MULTIPLE-VALUE-RETURN and RETURN-LIST
Reminder: MULTIPLE-VALUE is essentially the same as MSETQ-CALL of
previous notes. The names MSETQ-CALL and MSETQ-RETURN will be
superseded by the LISPM names; however macros to convert them will
be provided in the UMLMAC file (Utility MacLisp MACros).
[more exposition below]
2) Additional, new "out-of-core" SUBRs and MACROs:
Two LSUBRs "<=" and ">=", of 2 or more args are autoloadable from MLSUB file
SOURCE-TRANS properties are set up, in the MLMAC file, for
LOGAND, LOGIOR, LOGXOR, LOGNOT, FIXNUMP, FLONUMP, EVENP, <=, >=, <, and >.
(see item 4 below for "SOURCE-TRANS"), and these are used to
generate some other SUBRs in the MLSUB file:
LOGAND, LOGIOR, LOGXOR, LOGNOT,
LISTP, FIXNUMP, FLONUMP, and EVENP.
Non-autoloading macro available in DEFMAC: DEFUNP
Non-autoload versions of FMAKUNBOUND, FSYMEVAL, and FSET are in FUNCEL file.
[more exposition below]
3) Default value for DEFUN&-CHECK-ARGS is now (), and whenever &OPTIONAL or
&REST args are specified, the "args property" of the symbol will be set.
[more exposition below]
DEFUN&-CHECK-ARGS is the variable which says whether or not there should
be code in the function itself to do number-of-args checking.
The interpreter, and "UUO" handler, when in *RSET mode, will check the
number of arguments passed to a LSUBR/SUBR against the "args property",
which is retrieved and set by the ARGS function.
4) SOURCE-TRANS properties for COMPLR act almost like LISPM "optimizers".
[more exposition below]
5) FILE-EXIT-FUNCTIONS is a new global variable which is lambda-bound to
the value of FILE-EXIT-FUNCTIONS-DEFAULT by LOAD and FASLOAD.
It holds a list of functions of 1 arg to be run at end of loading.
[more exposition below]
6) DEFSFA, a macro for defining macros to make SFA usage easier, is now
defined in the EXTMAC file (along with DEFCLASS* and DEFMETHOD*)
see the documentation file SFA.DOC (on ITS system -- .INFO.;LISP SFA)
for full information.
_______________________________________________________________________
1) Multiple-value capability implemented thru some autoloadable things:
New AUTOLOADable macros and capabilities from MLMAC:
MULTIPLE-VALUE, VALUES, MULTIPLE-VALUE-BIND
Autoloading SUBRs from file MLSUB:
MULTIPLE-VALUE-LIST, VALUES-LIST, and SI:CHECK-MULTIPLICITIES
Non-autoloading macros available in MLMAC:
MULTIPLE-VALUE-RETURN and RETURN-LIST
Reminder: MULTIPLE-VALUE is essentially the same as MSETQ-CALL of
previous notes. The names MSETQ-CALL and MSETQ-RETURN will be
supersede by the LISPM names; however macros to convert them will
be provided in the UMLMAC file (Utility MacLisp MACros).
Frequently, it is convenient to think of a function as returning
several values; in LISP, one often just constructed a list of the
several item, and the calling function would "destructure" that list.
The basic special forms MULTIPLE-VALUE and VALUES are provided to
indicate respectively a function call which is expected to return
(possibly) multiple values, and a function exit which does provide
(possibly) multiple values. Cooperation is achieved through a
"return-values vector", which in MacLISP is just a collection of
several special variables. MULTIPLE-VALUE is somewhat like SETQ
in that the multiple-values returned by the call will be set into
some variables; e.g.,
(MULTIPLE-VALUE (AVERAGE MAX STANDARD-DEVIATION)
(STATISTICS-GATHERER x1 y1 ...))
might set up three values in the variables AVERAGE, MAX, and
STANDARD-DEVIATION, but without requiring an intermediate list of
results. Similarly,
(MULTIPLE-VALUE-BIND (AVERAGE MAX STANDARD-DEVIATION)
(STATISTICS-GATHERER x1 y1 ...)
(do-something ...)
...
(do-last-thing ...))
provides a lambda-binding, rather than a setting, of the variables,
over the enclosed scope. Also, for example, the routine
STATISTICS-GATHERER might look like
(DEFUN STATISTICS-GATHERER (a1 a2 ...)
... ;lotta work here!
(VALUES (//$ SUM N) HIGHEST (COMPUTE-SD)))
The value of the form (MULTIPLE-VALUE (X ...) ...) is the thing
which got set to X; since destructuring works with MULTIPLE-VALUE,
then (MULTIPLE-VALUE (() Y ...) ...) returns the thing which would
have been set to the first variable, had it not been ().
MSETQ-CALL and MSETQ-RETURN are being superseded by the LISPM names,
which are now essentially equivalent; minor differences are noted by
an occurrence of **** in the documentation here below.
1a) MULTIPLE-VALUE, in MacLISP, macroexpands into code to setq the requested
variables to the multiple values returned by a function call. E.g.
(MULTIPLE-VALUE (FORM EX?) (MACROEXPAND-1*M FORM))
calls a macroexpander which returns two values -- the first is the
possibly expanded form, and the second is a flag saying whether or
not any expansion really happened. If there aren't enough returned
values to set all the indicated variables, the default action of the
MacLISP facility is to pad out with ()'s (same as on LISPM);
however, **** if the global variable SI:CHECK-MULTIPLICITIES is
set to CERROR, an error will be signalled instead. See the
discussion under item 4 below.
1b) VALUES is a new LISPM special form, and in NIL/MacLISP it is
essentially the same thing as MSETQ-RETURN was; its basic action is
to set up a "return-values vector"; typical usage would be to
call VALUES as the last form in a lambda-expression. Example:
(DEFUN TWIST (X Y)
(COND ((AND (NUMBERP X) (NUMBERP Y))
(VALUES 'T (LESSP X Y)))
('T (SETQ X (TO-STRING X) Y (TO-STRING Y))
(VALUES () (ALPHALESSP X Y)))))
1c) MULTIPLE-VALUE-LIST constructs a list of all the (possibly multiple)
values returned by the evaluated sub-form. Format of usage is like
(MULTIPLE-VALUE-LIST (<fun> ...))
where <fun> should return some (possibly multiple) values.
1d) RETURN in MacLISP still admits only one argument **** -- in order to do
a RETURN with multiple arguments, do (RETURN (VALUES first second ...))
MULTIPLE-VALUE-RETURN is primitive on the LISPM, but is macro expanded
in MacLISP to use merely RETURN. Currently, RETURN (but not
MULTIPLE-VALUE-RETURN) is primitive in MacLISP, and this causes one
incompatibility -- (RETURN (VALUES ...)) on the LISPM might return
only one value, but in MacLISP it will return as many values as are
provided by the VALUES; also, if FOO is a function returning
multiple values, then (RETURN (FOO)) will "pass them all thru" doing
essentially what MULTIPLE-VALUE-RETURN does on the LISPM.
1e) VALUES-LIST is a SUBR of one argument, a list, which it "spreads out"
into the "return-values vector"; Thus (VALUES-LIST '(1 B 3))
is the same as (VALUES 1 'B 3).
RETURN-LIST macroexpands into something like
(MULTIPLE-VALUE-RETURN (VALUES-LIST ...))
As mentioned above for MULTIPLE-VALUE-RETURN, there is the implicit
LISPM/MacLISP incompatibility about RETURN.
1f) MULTIPLE-VALUE-BIND -- a form is to be evaluated, returning several
values, and *then* a lambda-binding contour is created, with
the values bound to some variables; following that, the body of
and implicit PROGN is executed. Example:
(MULTIPLE-VALUE-BIND (A B C) (GET-THREE-VALS ...)
(COGITATE-UPON A)
(LIST B C))
1G) SI:CHECK-MULTIPLICITIES **** is called whenever MULTIPLE-VALUE or
MULTIPLE-BIND have more variables than there are returned values;
the value of SI:CHECK-MULTIPLICITIES, as a variable, then determines
what to do (default setting is null):
() -- means pad out unsupplied multiple-return-values with nulls;
CERROR -- means run an error if not enough values supplied;
any thing else should be a function to funcall with an argument which
is the number of variables minus one (*:ARn contains the
actual number of returned values).
Remember also that MULTIPLE-VALUE depends upon a "return-values vector" being
set up by the function called, and thus constructs like
(MULTIPLE-VALUE (v1 v2) (PROG1 (MANY-VALUED-FUN a1 a3) (SOMETHING-ELSE)))
will not work in general; a correct way to do this particular example is
(LET (unique-var-1 unique-var-2)
(MULTIPLE-VALUE (unique-var-1 unique-var-2) (MANY-VALUED-FUN a1 a3))
(SOMETHING-ELSE)
(SETQ v1 unique-var-1 v2 unique-var-2)
v1)
This "fault" of side-effecting also applies to MULTIPLE-VALUE-LIST.
The multiple-value functions operate quite efficiently for 8 or fewer
return values -- many of them are "open-coded" by virtue of the code
produced by the macroexpansions. Any returned values more than 8 are
passed via a cons'ing mechanism. Degenerate forms will generally
work OK, provided they make sense; e.g. (VALUES FOOBAZ) is just the
same as FOOBAZ, except the internal "number-of-extra-return-values"
variable is set up; (MULTIPLE-VALUE (X) ...) again will turn out
pretty much like an ordinary SETQ, and (MULTIPLE-VALUE () (FOO))
will turn out pretty much like (FOO), except that the internal
count variable is set up.
2) Additional, new "out-of-core" SUBRs and MACROs:
Two LSUBRs "<=" and ">=", of 2 or more args are autoloadable from MLSUB file
SOURCE-TRANS properties are set up, in the MLMAC file, for
LOGAND, LOGIOR, LOGXOR, LOGNOT, FIXNUMP, FLONUMP, EVENP, <=, >=, <, and >.
(see item 4 below for "SOURCE-TRANS"), and these are used to
generate some other SUBRs in the MLSUB file:
LOGAND, LOGIOR, LOGXOR, LOGNOT,
LISTP, FIXNUMP, FLONUMP, and EVENP.
Non-autoloading macro available in DEFMAC: DEFUNP
Non-autoload versions of FMAKUNBOUND, FSYMEVAL, and FSET are in FUNCEL file.
Each of <= and >= take two or more arguments; in addition, SOURCE-TRANS
properties are set up for <=, >=, < ,and > so that the case of three
or more arguments are "wrapped up in a LAMBDA" and the basic open-coding
action of the COMPLR on the binary version can be used.
NILAID permits usage of any of <, <=, >=, >, <$, <=$, >=$, and >$ with
two or more arguments; the "$" versions are for floating-point.
In conjunction with the functions which get SOURCE-TRANS properties
from the MLMAC file, there are SUBR definitions of them in this
file (MLSUB, which is acronymic for "MacLisp SUBrs"):
LOGAND, LOGIOR, LOGXOR, LOGNOT, FIXNUMP, FLONUMP, and EVENP.
For example, the definition of EVENP can be
(DEFUN EVENP (X) (EVENP X))
because the SOURCE-TRANS's cause "(EVENP X)" to expand into
"(NOT (ODDP X))"; similar tactics are used for multiple-argumented
funtions like LOGXOR etc.
Non-autoloading macro available in DEFMAC: DEFUNP
As on the LISPM, (DEFUNP FOO (<args>) e1 e2 ... en) macroexpands
into (DEFUN FOO (<args>)
(PROG ()
e1
e2
(RETURN en)))
Non-autoload versions of FMAKUNBOUND, FSYMEVAL, and FSET are in FUNCEL file.
By loading in the EXTEND feature, a pseudo SUBR object can be created
and manipulated; thus reasonable versions of the LISPM/NIL functions
FMAKUNBOUND, FSYMEVAL, and FSET are implemented.
This facility is pre-loaded into NILAID.
3) Default value for DEFUN&-CHECK-ARGS is now (), and whenever &OPTIONAL or
&REST args are specified, the "args property" of the symbol will be set.
DEFUN&-CHECK-ARGS is the variable which says whether or not there should
be code in the function itself to do number-of-args checking.
The interpreter, and "UUO" handler, when in *RSET mode, will check the
number of arguments passed to a LSUBR/SUBR against the "args property",
which is retrieved and set by the ARGS function.
4) SOURCE-TRANS properties for COMPLR act almost like LISPM "optimizers".
It is now possible to carry out "code-transformations" in COMPLR
by means of the SOURCE-TRANS mechanism. When compiling a form whose
CAR is a symbol, the compiler will check for a SOURCE-TRANS property
on the symbol. The value of this propery should be a list of
transformation routines, each of which must be a function of one
argument. Furthermore, each transformation routine must return two
values (e.g., via VALUES), the first being the transformed form and
the second being a flag which, when non-null, indicates that the
transformation routine has "done something". The compiler applies
each transformation routine in turn, passing the form to be
transformed as the sole argument. If the transformation routine
returns a second value of () then it is considered to have
"done nothing" and the next transformation routine is tried; otherwise
the routine is considered to have "done something" and the entire
process begins anew with the first transformation routine.
The transformation of the original form is complete only after all
transformation routines have been tried and "done nothing". This
transformation procedure is carried out fully before any macro
expansion is attempted.
Note well, that this differs from the LISPM facility in that the
translating functions *must* return at least two values.
5) FILE-EXIT-FUNCTIONS is a new global variable which is lambda-bound to
the value of FILE-EXIT-FUNCTIONS-DEFAULT by LOAD and FASLOAD.
It holds a list of functions of 1 arg to be run at end of loading.
The argument supplied to each function is null if loading completed
successfully; otherwise it is the file-array of the file being
aborted. This provision uses the UNWIND-PROTECT mechanism, so these
functions will be called even if the file is aborted by ^G or *THROW.
The initial setting of FILE-EXIT-FUNCTIONS-DEFAULT is null, so if you
set it to something else, those functions will be run at the end of
every file loading; typically, a file itself may push forms onto
FILE-EXIT-FUNCTIONS to provide for individual "cleanup".