Saturday Jan 27,1979 LQ+7D.1H.40M.31S. LISP 1785 / COMPLR 867 -JONL-
1) EVAL-WHEN - - a new fsubr, like DECLARE but much more general
2) DEFUN permits LISP-Machine like syntax, and LET-destructuring of arguments.
3) New AUTOLOADable MACROs: LET, LET*, DESETQ; and DEFMACRO, MACRO, DEFUN&
Functions MACROEXPAND and MACROEXPAND-1, defined as on LISPM, are available
4) Better error checking in *RSET mode for functions that cdr down lists:
LAST now gets the last node of a non-atomic s-expression, or () for ().
5) "MACLISP" is now on the feature list, to help distinguish from LISPM.
6) COMPLR has some new switches and global variables - EXPAND-OUT-MACROS etc.
7) SUSPEND - review of meanings of arguments
8) Under the ITS operating system, a JCL line with only a <space> means don't
use any INIT file, even if the connected directory has one. This may
be extended to the TOPS versions also.
____________________________________________________________________________
1) EVAL-WHEN - - a new fsubr, like DECLARE but much more general
(EVAL-WHEN (<id1> <id2> ... <idn>) <foo1> <foo2> . . . <foon>)
will cause the evaluation of the various <fooi> only if the "evaluator"
matches one of the indicators in the first list; these indicators <idi>
may be among EVAL, COMPILE, or LOAD, which respectively trigger
EVAL - a normal, read-eval-print loop
COMPILE - the "maklap" processor, which compiles files
LOAD - "fasload" (which only processes compiler output)
(EVAL-WHEN (COMPILE) (SAY THIS)) is entirely equivalent to
(DECLARE (SAY THIS))
(EVAL-WHEN (EVAL LOAD) (RUN THAT)) is generally equivalent to
(RUN THAT)
(EVAL-WHEN (LOAD) (PRINT '|Loading Compiled version of Foo|))
will cause the print request to appear only in the compiled FASL
file, and be run at load time. (or LAP file if you don't assemble).
(EVAL-WHEN (EVAL COMPILE LOAD) (SETSYNTAX '/% 'MACRO 'FUNNY-FUN))
causes evaluation in all environments, which is often what one wants
with macro characters.
2) DEFUN permits LISP-Machine like syntax, and LET-destructuring of arguments.
DEFUN automatically becomes DEFUN& if "&" keywords occur in the dummy
argument list, or any dummy argument is not a symbol; see 3b below.
3) New AUTOLOADable MACROs: LET, LET*, DESETQ; and DEFMACRO, MACRO, DEFUN&
Functions MACROEXPAND and MACROEXPAND-1, defined as on LISPM, are available
from the file supporting DEFUN&, but they do not have autoload properties.
LET, LET*, and DESETQ are on the same file LISP;LET FASL
DEFMACRO, MACRO, and DEFUN& are on the file LISP;DEFMAC FASL
In the BNF descriptions below, "{...|...}" denotes precisely one of
the alternatives between the brackets and separated by vertical-bars;
"{...}*" means zero or more occurances of the alternatives, "{...}+"
means one or more occurances.
3a) LET, LET*, and DESETQ
Following the many user definitions of a macro LET, we now
have an autoload property for LET, and a definitions of it
which is fairly intuitive:
(LET ((A <e1>) (B <E2>) ... (C <en>))
<computate>)
macro-expands into
((LAMBDA (A B ... C) <computate> )
<e1> <e2> ... <en>)
In certain arcane instances, one wants a sequential binding, rather
than the parallel binding that occurs for a multiple-variable LAMBDA;
thus, LET* may be used:
(LET* ((A <e1>) (B <E2>) ... (C <en>))
<computate>)
macro-expands into
((LAMBDA (A)
((LAMBDA (B)
...
((LAMBDA (C)
<computate> )
<en>)
... )
<e2>)
<en>)
In all other respect, however, LET* is similar to LET. One
especially useful feature which the MACLISP macro for LET has is
that of "pattern decomposition": a general data pattern may be used
in each place where a variable is expected; and for each combination
of data-accessing functions which access a non-null symbol in the data
pattern, there is set up a binding between that symbol and the same
data-accessing path applied to the "argument" expression (that is,
one of the <ei>). Thus nullist in a pattern means "ignore". A simple
example should suffice, but also a BNF description is given.
(LET ( ((A . B) <e1>)
((() C () D) <e2>)
(TEMP1)
TEMP2 )
<computate>)
expands into something that operates like
((LAMBDA (G0001 G0002 A B C D TEMP1 TEMP2)
(SETQ A (CAR G0001))
(SETQ B (CDR G0001))
(SETQ C (CADR G0002))
(SETQ D (CADDDR G0002))
<computate>)
<e1> <e2> () () () () () () )
Just exactly what code comes out of the LET macro depends on many
things, but the intent is to "decompose" the argument, according
to the structure of the pattern of variables, and bind the variables
correspondingly.
DESETQ is similar, but there is no "binding" involved - only
"set"ing. For example,
(DESETQ (A . B) (MUMBLIFY))
might become
((LAMBDA (G0001) (SETQ A (CAR G0001) B (CDR G0001))) (MUMBLIFY))
When compiled, the extra variable G0001 may not cause any noticeable
slowdown in the running of such code, but if the item being
destructured is denoted by a variable, then there is no new LAMBDA:
(DESETQ (() C () D) XVAR)
might expand into
(SETQ C (CADR XVAR) D (CADDDR XVAR))
A given instance of LET or DESETQ usage will be "DISPLACED" or
not depending on the value of the variable DEFMACRO-DISPLACE-CALL;
See 3c below for more information about the use of this flag.
In point of fact, LET is continually being extended to know
about structures other than lists; thus in NIL, one may destructure
thru VECTORs also, and thru a "record" created by the structure
package DEFVST (currently on LIBDOC and LIBLSP). But leaving
aside these more arcane data structure for now, a BNF description
would be
( LET ( { <symbol> | ( <pattern> <computation> ) }* )
{ <s-exp> }* )
where a "<pattern>" may be a symbol, or the nullist, or any list
(or "vector", or "defvst") structure. Also:
( DESETQ <pattern> <computation> )
3b) DEFUN&, for maclisp compatibility with the extended DEFUN syntax
of the LISPMachine, using "&OPTIONAL" and "&REST"
Also, note that if DEFUN notices the occurance of any of the
keywords &OPTIONAL, &REST, or &AUX in the defining arglist, the
the form is automatically turned into a DEFUN& (which may have
to be autoloaded). This way, it will appear that MACLISP
supports the extended syntax. Let an "<arglist>" be defined
by BNF as follows:
( {<pattern>}* { &OPTIONAL { <symbol> | ( <pattern> <s-exp> ) }* }
{ &REST <symbol> }
{ &AUX { <symbol> | ( <pattern> <s-exp> ) }* } )
Then the extended DEFUN syntax is defined by
( DEFUN { <symbol> | (<symbol> <symbol>) | (<symbol> <symbol> <symbol>) }+
{ EXPR | FEXPR | MACRO | | }
{ <symbol> | () | <arglist> }
{ ( DECLARE { <s-exp> }* ) | | }
{ <s-exp> }* )
Note that this allow pattern decomposition at each argument
position of a function definition; if a single symbol, say <sym>
occurs in the optional list, it is treated as if it were of the
form "(<sym> () )" - this way there is no ambiguity caused by
the permission of <pattern>s in the optional list, for the use
of such must be in the default-value-supplied form. Also, the
order of evaluation of the default values for optional arguments,
and of the values for the auxillary variables, is strictly
left-to-right, **after** all the non-optional argument bindings
have been made. Here is an example with a lot of "bells-and-whistles"
just for illustrative purposes:
(DEFUN FOO ( (() NAME VARLIST . BODY)
KIND
&OPTIONAL (PS-FLAG (AND (EQ (CAAR BODY) 'DECLARE)))
((DNAM . DLST) (AND PS-FLAG (CADAR BODY)))
&REST W
&AUX (N (COND (PS-FLAG 5) (6)))
)
(WORK-IT-OUT ...))
Thus FOO requires at least two arguments; and two more will be further
bound, one into PS-FLAG, and the other destructured into (DNAM . DLST)
3c) DEFMACRO, MACRO -- macro-producing macros, compatible with LISPM.
Three flags are noticed during instances of the macro expansions:
DEFMACRO-CHECK-ARGS (default = T)
DEFMACRO-DISPLACE-CALL (default = T)
DEFMACRO-FOR-COMPILING (default = T)
The first flag if non-null, produces a macro which checks each
instance of usage for compatible numbers of "arguments"; since this
checking takes time, it may not be desirable in all circumstances.
The second if non-null, produces a macro which calls
DISPLACE in order to displace out the original macro call.
The macros MACRO-DISPLACE and DEFMACRO-DISPLACE exist, just
as in the LISPM, which do not pay attention to this flag, but
rather always yield a product which uses DISPLACE.
The third determines which of the two macro-defining forms
will be used: (DEFUN foo MACRO ...) or (DEFUN (foo MACRO) ...)
If non-null, the latter will be used so that the macro will be
compiled by the compiler (whereas the former format is intended
primarily for macros used interpretively, or as compilation aids;
see 5b below.
DEFMACRO admits a "bound-variable-list" that is reminiscent of
the standard argument-list processing:
( {<pattern>}*
{&OPTIONAL {<symbol> | (<pattern> <default.evaluation>) }+ }
{&REST <symbol>} )
As with DEFUN&, a single symbol, say <sym>, in the &optional list
is treated as if it were of the form "(<sym> () )", for purposes
of default initializations.
Examples:
(MACRO ERRBRK (X) (COND ((EQ (CADR X) 'BARF) '(ERR))
(`(PROG2 (PRINC ',(cadr x)) (BREAK ERROR)))))
(DEFMACRO ERRBRK (MSG &OPTIONAL (BKTYPE 'ERROR))
(COND ((EQ (CADR X) 'BARF) '(ERR))
(`(PROG2 (PRINC ',msg) (BREAK ,bktype)))))
4) Better error checking in *RSET mode for functions that cdr down lists:
LAST now gets the last node of a non-atomic s-expression, or () for ().
In *RSET mode, the time is taken to check that no attempt is made
to take the cdr of a non-null atom in the functions
NTH, NTHCDR, APPEND, NCONC, REVERSE, NREVERSE, NRECONC, ASSQ, MEMQ, DELQ
Regardless of the setting of *RSET, the following functions will
not cdr through a non-null atom:
LAST, MEMBER, ASSOC, DELETE, all MAP series.
[In LISP versions prior to about 1783, LAST had the bug that it would
begin cdr'ing down the plist of any symbol at the termination of a
non-standard list - try (LAST '(A . CAR))]. Note however, if any of the
MAP series gets expanded into a DO loop by the compiler, the endtest will
be replaced by NULL rather than ATOM.
5) "MACLISP" is now on the feature list, to help distinguish from LISPM.
(STATUS FEATURE LISPM) is non-null for the LISP machine
(STATUS FEATURE MACLISP) is non-null for all PDP10 and MULTICS MACLISPs
(STATUS FEATURE NIL) is non-null for any real or simulated NIL.
6) COMPLR has some new switches and global variables - EXPAND-OUT-MACROS etc.
6a) new switch - H for variable EXPAND-OUT-MACROS
Toplevel forms which are not functions to be compiled (or other
wise specially treated by MAKLAP) could be fully macro-expanded
before being output to the FASL file. Normal setting is non-null
meaning to do this expansion.
6b) repeat of meaning of the M switch - variable MACROS
MAKLAP will not cause the compilation of a form like
(DEFUN <foo> MACRO (<var>) ...) when it is processing a file,
for it assumes that this macro is only for aid during compilation.
If MACROS is non-null, it will also output an expr form for such
a macro into the FASL file. Remember that if the definition is like
(DEFUN (<foo> MACRO) (<var>) ...), then the compiled version of the
macro will always be output. In either case, COMPLR remembers the
expr definition for use during the subsequent parts of the file.
6c) new variable - MAKLAP-DEFAULTF-STYLE
The command line read maklap usually consists of two file specs
separater by a left-arrow (underscore in new ascii); the filling
in of the unspecified components of a file spec can be done either
from the accumulated left-to-right mergeing, or begin separately
for input and output file specs. MIDAS style is the former, and
the value of this new variable either is MIDAS or ().
6d) when making up, can set feature NO-EXTRA-OBARRAY
(SSTATUS FEATURE NO-EXTRA-OBARRAY) will permit CCLOAD to make
up a compiler without the COBARRAY/CREADTABLE which separates
user environment from compiler environment. If saving about 1.5K
or so words means that much to you, and taking a chance means
very little . . .
7) SUSPEND - review of meanings of arguments
[Original information in the LISP NEWS file, under dates
5/22/74 JAN 13,1978 June 14,1978 ]
If no arguments are given, then a return to monitor is preceeded by
the message ";$Suspended$" (in ITS, it is ":Suspended", and those
are alt-modes rather than dollar-signs).
First arg - string for printing to exec; null; or (on ITS) small fixnum.
Ordinarily, when the suspended LISP returns to the monitor, it
will print the message ";$Suspended$", but a non-null symbol will
be printed instead; null means continue immediately, possibly after
dumping out into the file specified by the second argument.
For ITS system, the message printed out will be executed by DDT, just
like a string to VALRET; if the argument is a fixnum, it will be
taken as the value to put in the right half of a .BREAK 16,.
Second arg - file name in which to dump the pure parts of the system
For ITS system, the job is PDUMPd, with an "indirect" symbol table;
the pages shared with the system-dumped TS LISP are not dumped
if (STATUS FLUSH) is non-null. Since a LISP tries to share its
read-only pages with the system-dumped TS LISP, the only reason
for allowing them to be copied out into the dump'd file when
SUSPENDing is the fear that the system-dumped TS LISP may
inadvertently disappear off the file system.
For TOPS-10 systems (and SAIL), the high segment of a two-segment
job is dumped into this file; one must still type a SSAVE (or
or SAVE) at the monitor in order to dump the low segment. But
if (STATUS FLUSH) is non-null, then no dumping of the high
segment occurs, and it is flushed before returning to the monitor,
so that when the dumped low segment is re-activated, it will try
to retrieve the high segment associated with the original
LISP.SHR file. Caution! As of Jan 1979, there may still be
bugs in the non-its version of SUSPEND.
8) Under the ITS operating system, a JCL line with only a <space> means don't
use any INIT file, even if the connected directory has one. This may
be extended to the TOPS versions also.