Trailing-Edge - PDP-10 Archives - decuslib10-04 - 43,50322/lspdoc.doc
There are no other files named lspdoc.doc in the archive.


 Extended Lambda Expressions

      When solving problems  in  LISP,  it is very often convenient to
 have a function which executes more  than one form but does  not need
 the  variable  and  label  features  of  PROG.   We  have  added this
 capability to UCI LISP by extending LAMBDA expressions to handle more
 than one form.


         When  such  a  LAMBDA  expression is  applied  to  a  list of
         arguments each FORM is evaluated in sequence and the value of
         the LAMBDA expression is FORMn (after the arguments are bound
         to the LAMBDA variables).


         ((LAMBDA(X) (CAR X) (CDR X)) (QUOTE (A)))    = NIL
         ((LAMBDA(X Y) X Y (CONS X Y)) NIL T)    = (NIL . T)

         This means that functions defined by DF or DE evaluate all of
         forms in their definition,  instead of just the first  one as
         in Stanford's  version.   The  value  of  the function is the
         value of the last form.

 WARNING:  This  is not a PROG; GO and RETURN do not have the expected

                                      3 . 1

 The Functions PROG1 and PROGN

 (PROG1 X1 X2 ... Xn) ,n<6

         PROG1 evaluates all expressions X1 X2 ...   Xn and returns X1
         as its value.

 (PROGN X1 X2 ... Xn)

         PROGN evaluates all expressions X1 X2 ...   Xn and returns Xn
         as its value.

                                      3 . 2

 Conditional Evaluation of Forms

 (SELECTQ X "Y1" "Y2" ... "Yn" Z)

         This very useful function is  used to  select  a  sequence of
         instructions  based  on  the value of its  first  argument X.
         Each of the  Yi is a list of  the form  (Si E[1,i] E[2,i] ...
         E[k,i]) where Si is the "selection key".

         If Si is an atom the value of X is tested to see if  it is EQ
         to  Si (not evaluated).   If so,  the  expressions E[1,i] ...
         E[k,i] are evaluated in sequence, and the value of SELECTQ is
         the value of the last expression evaluated, i.e. E[k,i].

         If Si  is a list, and if any element (not evaluated) of Si is
         EQ to the value of  X,  then E[1,i] ...  E[k,i] are evaluated
         in turn as above.

         If Yi is  not selected  in one of the two ways described then
         Y[i+1]  is tested,  etc.  until all the Y's have been tested.
         If none is  selected, the value of SELECTQ is the value of Z.
         Z must be present.

         An example of the form of a SELECTQ is:

         (SELECTQ (CAR W)
                  (Q (PRINT FOO) (FIE W))
                  ((A E I O U) (VOWEL W))
                  (COND (W (QUOTE STOP))))

         which has  two  cases,  Q  and  (A E I  O  U)  and  a default
         condition which is a COND.

         SELECTQ compiles  open,  and is therefore very fast; however,
         it  will  not work if  the  value of X  is  a  list,  a large
         integer, or floating point number, since it uses EQ.

                                      3 . 3

 Changes to the Handling of Errors


         ERRSET has been changed slightly.  If F=NIL the error message
         is suppressed  and  the error will not cause a  break  to the
         Break Package.   If F is not  given then  ERRSET assumes that
         F=T.   If F=0  (i.e.  zero)  then the  error  message will be
         printed on the  current  output device,  otherwise it will be
         printed on the teletype.

 (ERR E)

         There is now a special case of ERR.   If the  value  of  E is
         ERRORX,  then ERR will return to the most recent ERRSET which
         has F=ERRORX.   This allows  two levels of user errors.  If a
         Control-G is typed  in by the user it generates a (ERR (QUOTE
         ERRORX)).   This  means that the user can now protect himself
         against this type of input error.


         ERROR generates  a  real  LISP  error.   E  is  evaluated and
         printed (unless error  messages  are suppressed)  and  then a
         break occurs just as for any other LISP error.

                                      3 . 4



         APPLY# is similar to APPLY except that  FN may be  a function
         of any type including  MACRO.  Note that when either APPLY or
         APPLY# are given an EXPR as their first argument,  the second
         argument is evaluated by APPLY# or APPLY, but the elements of
         the resulting list are directly bound to the lambda variables
         of  the  first argument,  and  are not  evaluated  again even
         though it is an EXPR.

 (APPLY# (QUOTE PLUS) (QUOTE (3 2 2))) = 7

 (NILL "X1" "X2" ... "Xn") = NIL

         This function  allows the user to stick  S-Expressions in the
         middle  of  a  function definition  (e.g. as  a PROG element)
         without having them evaluated or otherwise noticed.   NILL is
         also useful for giving a dummy definition to a function which
         has not yet been defined.

                                      3 . 5


 Project-Programmer Numbers for Disk I/O

 In all I/O  functions (including INPUT  and OUTPUT), the use of a two
 element list (not a dotted pair)  in place of a device will cause the
 function to assume DSK:  and  use the list as  the project-programmer

 Saving Function Definitions, etc. On Disk Files


         DSKOUT is  an FEXPR and  is used  to create an  entire output
         file  on  disk file  DSK:  "FILE".  It sets the linelength to
         LPTLENGTH,   and   evaluates   all   of  the  expressions  in
         "EXPRSLIST".  If an expression on "EXPRSLIST" is atomic, then
         that  atom  is  given  to  GRINL  instead of  being evaluated
         directly.   If the value  of FILBAK  is non-NIL and  the file
         already exists,  DSKOUT  will attempt to rename the file with
         an extension of the value  of FILBAK.   An error message will
         be printed on  the  TTY:  if the  file  cannot  be backed up.
         FILBAK is initially set to LBK.

 For example, if FNLIST is a list of your functions, they can be saved
 on a disk file, FUNCS.LSP by:


 and the file  FUNCS.LSP  will be renamed to FUNCS.LBK  if  it already

                                      4 . 1

 Reading Files Back In


         READ-EVAL-PRINTs  the contents  of the  given files.  This is
         the function to use to read files created by DSKOUT.

         Reads FUNCS.LSP from DSK: and DATA.LSP from DTA0:.

         (DSKIN (667 2) (DSKLOG.LSP))
         Reads DSKLOG.LSP from the disk area of [667,2].

                                    4 . 1 . 1

 Reading Directories

 The following  functions  are  for  reading  directories.   UFDINP is
 analogous  to  the function  INPUT  in  that  it  opens  a  file on a
 specified  channel.  The channel must be selected via INC in order to
 be read.   The file is opened in binary  image mode and should not be
 read by the normal LISP read functions.   All functions are SUBRS and
 thus evaluate their arguments.


         UFDINP opens the directory of PPN on CHANNEL.  It returns the
         value of CHANNEL  as it's result.   PPN is either of the form
         (PROJ PROG)  where  PROJ and PROG are  both inums or NIL.  If
         PPN is NIL the user's directory is assumed.


         *(UFDINP T (QUOTE (2206,1)))



         RDFILE returns the next file in the directory that is open on
         the current input channel.   It return a file which is either
         an atom or an atomic dotted pair.   It  does  an  (ERR $EOF$)
         when it reaches the end of file.


         *(PROG (X) (INC (UFDINP T NIL) NIL)
                    (SETQ X (ERRSET (RDFILE)))
                    (INC NIL NIL)
                    (COND ((CONSP X)(RETURN (CAR X)))

         (INIT . LSP)

                                    4 . 1 . 2


         DIR returns a list of  files from the directory  of  PPN.  If
         PPN is NIL, the user's directory is assumed.

         (DIR (QUOTE (2206 4)))

         ((INIT . LSP) (FOO .LSP) MYFILE))

                                    4 . 1 . 3

 File Manipulation

 The following functions enable the user to manipulate files  in those
 directories to  which  he  has  legitimate access.  The definition of
 access  privileges  is  system  dependent.   These  functions use the
 RENAME UUO  to  effect  the  desired  manipulations.   A  FILESPEC is
 defined as follows:


 A DEV is either an atom whose last character is a colon, I.E.
 DSK: or a a list of the form:


 where PROJ and PROG are both numbers.  DEV is optional and if
 ommitted the user's disk area is assumed.

 A FILNAM is either an atom or an atomic dotted pair.


         (FILE . EXT)


         *RENAME  is  a SUBR that  renames FILESPEC1 to FILESPEC2.  It
         returns  T if the rename is  successful  and NIL if it fails.
         If a  device  is specified  in  FILESPEC1  and  no  device is
         specified in  FILESPEC2 the device specified in  FILESPEC1 is
         carried over to FILESPEC2.  Thus:

         (*RENAME (QUOTE ((2206 4)(FOO . LSP)))
                  (QUOTE ((FOO . BAK))))

         is equivalent to:
         (*RENAME (QUOTE ((2206 4)(FOO . LSP)))
                  (QUOTE ((2206 4)(FOO . BAK))))

         If no device is specified in either FILESPEC, the user's disk
         area is assumed.

                                    4 . 1 . 4


         RENAME is an FSUBR  that  renames  FILNAM1  to  FILNAM2.  The
         DEV's  are  optional.   If  DEV2  is not  specified,  DEV1 is
         assumed.  If both DEV's are not specified, the default is the
         user's  disk  area.   RENAME  returns  T  if  the renaming is
         successful and NIL if it fails.


         *(RENAME DSK: (FOO . LSP)(FOO . BAK))

         *(RENAME FOO FIE)

         *(RENAME (2206 4)(FOO . LSP)(2206 3)(FOO . LSP))



         DELETE is an FSUBR that  deletes the files in  the list.  The
         DEV's are optional, and a DEV is effective over the following
         FILNAM's  until  a  new  DEV  is  encountered.  DELETE always
         returns NIL.   The user's disk area is assumed  if no DEV has
         been specified.


         *(DELETE FOO (FOO1 . LSP) (2206 4) (OLDFIL . COM))


                                    4 . 1 . 5


         FILBAK is  a SUBR  that  attempts  to  rename  FILE  with the
         extension  of NEWEXT.   FILE  can  be either  a  FILNAM  or a
         FILSPEC.  FILBAK returns T if the renaming was successful and
         NIL if it fails.



         will rename the file FOO to FOO.BAK.


         will rename the file FOO.LSP to FOO.BAK.

         (FILBAK (QUOTE ((2206 4) (FOO . LSP)))
                 (QUOTE BAK))

         will rename the file FOO.LSP[2206,4] to FOO.BAK[2206,4].


         MYPPN  returns the user's project programmer number in a form
         suitable for use by the directory and I/O functions.



         (2206 4)


         LOOKUP is a SUBR that determines whether the file  DEV FILNAM
         exists or not.   LOOKUP returns NIL if it can't find the file
         and (LIST DEV FILNAM) if the file does exist.  If DEV is NIL,
         DSK: is assumed and (LIST FILNAM) is returned.

                                    4 . 1 . 6

 Queueing Files


         QUEUE  is an  FSUBR that queues files to the specified device
         or  queue.  It is essentially the same as the monitor command
         QUEUE,  both in  syntax and effect.   The  main  use  of this
         function is to get output to line printer, paper tape punches
         etc.  However, the input queue can also be specified in order
         to batch a job.

         A queue name QNAM:  is an atom of  three to six letters whose
         last letter is a colon.  The first three letters indicate the
         general queue (see below)  and the following letters indicate
         the specific queue.

         PLT     =PLOTTER QUEUE
         CDP     =CARD PUNCH QUEUE
         INP     =JOB BATCH QUEUE

         Thus (QUEUE LPT: ...) would queue to the line printer without
         specifying a specific line printer queue.   (QUEUE LPT0: ...)
         would queue to line printer 0.  As in the monitor command, if
         the  queue  name  QNAM:  is not specified,  the default is to

         If an INPUT  queue is  specified,  a  maximum of two files is
         permitted.   The  second file is taken as the name of the log
         file.  If it is not specified, the filename of the first file
         with an extension of .LOG is assumed.

                                    4 . 1 . 7

         Switches consist of  two  element  lists,  the  first element
         being the  switch and the second the value.  In the case of a
         required  non-numeric value (as in DISP) only the first three
         letters of the argument are looked at  i.e.  PRESERVE and PRE
         are equivalent.


                             TO BE OUTPUT
         DISP   'PRE'        PRESERVE FILE          ALL
                             'REN'                  RENAME FILE OUT OF
                                                    DIRECTORY AND DELETE
                                                    AFTER SPOOLING    ALL
                             'DEL'                  DELETE AFTER SPOOLING ALL

         Defaults are system defined except for DISP which defaults to
         PRE so that all files are preserved.

         As  in the  monitor command,  switches  are  in  effect until
         superseded by  another instance of  the switch.  Switches may
         precede the first file or device.

         DEV's are either an atom whose last character is a colon or a
         ppn specification.  A device affects only the files following
         it.   It is  superseded  by another device.   If no device is
         specified, DSK: is assumed.

                                    4 . 1 . 8


         *(QUEUE LPT: DSK: FOO (FOO .  LSP))

         prints the files FOO and FOO.LSP on the line printer.

         *(QUEUE LPT: (FOO . LSP)(COPIES 2))

         prints two copies of FOO.LSP on the line printer.

         *(QUEUE INP: (FOO . CTL))

         queues a job using FOO.CTL as its command file. Leaves a LOG
         file in FOO.LOG.

         *(QUEUE INP: (FOO . CTL)(FOO . LOG))

         same as above.

                                    4 . 1 . 9

                      Recovery From QMANGR Errors

      The QUEUE function must  swap  the  LISP  high  segment  for the
 QMANGR high segment.   It then transfers control to  the  QMANGR high
 segment.   In most cases,  if QMANGR finds an error, it simply prints
 an error message.  In a few cases, however, it returns control to the
 monitor.   The REE command will restore the appropriate  high segment
 and processing will continue.  Note that in this instance, the system
 does not wait for control characters.
      A  .START  command to the  monitor  will also restore the user's
 high segment.   However, this is not recommended as the allocation as
 the reallocation procedure will be entered.

                                    4 . 1 . 10

 Printing Circular or Deeply Nested Lists


         PRINTLEV is  a printing routine similar to  PRINT.  PRINTLEV,
         however,  only prints  to  a depth  of  DEPTH.   In addition,
         PRINTLEV recognizes lists which are circular down the CDR and
         closes  these with '...]' instead of ')'.  The combination of
         these two features allows PRINTLEV to print any circular list
         without an infinite loop.

         The value of PRINTLEV is the value of EXPRESSION.  This means
         that  PRINTLEV  should  not  be  used  at  the  top  level if
         EXPRESSION  is  a  circular  list  structure,  since the LISP
         executive would then attempt to print the  circular structure
         which is returned as the value.

 Spacing Control

 (TAB N)

         TAB tabs to position N on the output  line doing a  TERPRI if
         the current position is already past N.  Note should be taken
         that TAB outputs spaces only when  necessary  and outputs tab
         characters otherwise.

                                      4 . 2

 "Pretty Printing" Function Definitions and S-Expressions

 (GRINDEF "F1" "F2" "F3" ... "FN")

         GRINDEF is used to print the definitions of functions and the
         values of variables  in a format suitable for reading back in
         to LISP,  in what  is  known as DEFPROP format.  GRINDEF uses
         SPRINT  (see below)  to print these s-expressions in a highly
         readable  format,  in  which the levels of list structure (or
         parentheses  levels)  are indicated by  indentation.  GRINDEF
         prints  all the properties of the identifiers F1, F2, ..., Fn
         which appear on the list GRINPROPS.   If Fi is non-atomic, it
         will be SPRINTed.


         The variable GRINPROPS contains the properties which  will be
         printed by GRINDEF.   This variable can be set by the user to
         print special properties which  he  has placed on atoms.  The
         initial  value  of  GRINPROPS  is  (EXPR  FEXPR  MACRO  VALUE

 (GRINL "F1" "F2" ... "FN")

         GRINL  causes all of the  atoms, "F1" "F2" ...  "Fn", and all
         of the  atoms on the lists which are the values  of the atoms
         F1 F2  ...   Fn  to be GRINDEFed.  GRINL correctly prints out
         read macros and  is the  only function  which  does.  GRINDEF
         does not  save the  activation character for the read macros.
         Warning: Each Fi must be an atom.


         SPRINT is the function  which  does the "pretty  printing" of
         GRINDEF.   EXPR is printed in a human readable form, with the
         levels of list structure shown by indentation along the line.
         This is useful  for  printing large complicated structures or
         function  definitions.   The initial indentation  of  the top
         level  list  is  IND-1 spaces.   In normal use, IND should be
         given as 1.

                                      4 . 3

 Reading Whole Lines


         LINEREAD  reads a line,  returning it  as  a  list.   If some
         expression takes more than one line or a line terminates in a
         comma, space or tab, then LINEREAD continues reading until an
         expression ends at the end  of a line.   This is the function
         used by the EDITOR and BREAK Package  supervisors  to read in
         commands,   and  may  be  useful  for  other  supervisor-type


 *A B (C D
 *E) F G

 (A B (C D E) F G)

 *A B (C D E),
 *F G

 (A B (C D E) F G)

                                      4 . 4

 Teletype and Prompt Character Control Functions


         CLRBFI clears the Teletype input buffer.


         TTYECHO complements  the Teletype echo  switch.  The value of
         TTYECHO is T if the echo is being turned on, and NIL if it is
         being turned off.


         The LISP READ  routines type out a "prompt character" for the
         user  when they  expect  to  read  from  the  teletype.  This
         character  is normally  a  "*".   PROMPT  resets  this prompt
         character.   N is the  ASCII representation of the new prompt

         The  ASCII  representation  of the  old  prompt  character is
         returned as the  value of  PROMPT.   (PROMPT NIL) returns the
         current prompt character without changing it.


 *(PROMPT 53)


         Whenever LISP  is forced back to  the top level  (e.g.  by an
         error   or  Control-G),   the  prompt  character   is  reset.
         INITPROMPT is similar to PROMPT except that it  sets  the top
         level prompt character.   (INITPROMPT NIL)  returns the ASCII
         value of the top level prompt character without changing it.

                                      4 . 5


         READP  returns  T  if  a  character  can  be  input  and  NIL
         otherwise.  READP does not input a character.


         UNTYI unreads a character (such as a character input by a TYI
         or a READCH) and returns the ASCII code for that character.







         ERRCH changes the bell character that causes  an  (ERR (QUOTE
         ERRORX)).   N  is  the ASCII representation of the character.
         ERRCH returns the ASCII representation of the  old character.
         Note that if the new  character is not a  break  character to
         the monitor, it will not be processed until it is read in the
         normal course of reading.

                                    4 . 5 . 1


      Read Macros allow the user to specify a function to  be executed
 each time a selected  character is read  during input of his  data or
 programs.   This function is generally used  to produce  one  or more
 elements of the input list which  are built up in some way from later
 characters of the input string.   There are two types of Read Macros;
 Normal  Read Macros  whose  result is used as an element of the input
 list in the position  where the  macro character occurred, and Splice
 Macros whose result (must be a list  which)  is  spliced sequentially
 into the input list.

 WARNING:  Read macro characters will not be recognized if  they occur
 inside  of an atom  name unless the character is first defined  to be
 equivalent to a break or  separator character (e.g.  space  or comma)
 using MODCHR.

 Functions for Defining Read Macros


         CHARACTER is  defined as  a Normal Read Macro with "FUNCTION"
         being a  function name or a LAMBDA expression of no arguments
         which will  be evaluated each time CHARACTER is detected as a
         macro during input.   FUNCTION is put on the property list of
         CHARACTER under the  property READMACRO.  The value of DRM is

 Examples:       (DRM * (LAMBDA () (NCONS (READ)))
                 (DRM = (LAMBDA () (REVERSE (READ)))


         DSM is exactly like DRM except that CHARACTER is defined as a
         Splice Macro.

 Example:        (DSM : (LAMBDA () (CONS NIL (READ)))

                                      4 . 6

 Using Read Macros

      The use  of  Read Macros is  best described with  examples.  The
 Read Macros defined above will be used for the examples.

 Example 1

      If the expression (A B C = (D E F) G H) is read in the
 apparent input will be (A B C (F E D) G H).

 Example 2

      If (FOO1 FOO2 *FOO3 FOO4) is read the apparent input is
 (FOO1 FOO2 (FOO3) FOO4).

      In  each  case  the  associated  function was  evaluated and the
 result was returned as the next element of the input list.

 Example 3

      Reading (AT1 :(AT2 AT3) AT4) will result in
 (AT1 NIL AT2 AT3 AT4).

 Example 4

      If the input is (AA AB :AC) the result is (AA AB NIL . AC).

      It can be seen that the effect of a Splice Macro is to place the
 result  of the  function  evaluation into the input  stream minus the
 outermost set of parentheses.

                                      4 . 7

 Modifying the READ Control Table

      Since the LISP READ routines are table driven, it is possible to
 redefine  the meaning of a character by changing its table entry.  In
 each of the following functions CH is the ASCII representation of the
 character being modified.


         The value of MODCHR is  the old  table entry for CH.  If N is
         non-NIL  it must be a number which  represents a  valid table
         entry.   The entry  for CH is  changed to N.  If N is NIL, no
         change is made,  e.g. to make "." a letter (so it will behave
         like the letter "A") execute (MODCHR 56 (MODCHR 101 NIL)).


         SETCHR is similar to MODCHR except  that it only modifies the
         portion of the entry associated with read macros.

                                      4 . 8

 Reading without Interning


         RDNAM  functions  in the  same manner  as READ except that it
         does not intern the atoms  that it reads.   Thus an atom read
         by RDNAM and an atom read by READ are **NOT** EQ.


         *(PROG () (CLRBFI) (RETURN (EQ (RDNAM) (READ))))


                                      4 . 9

                        NEW FUNCTIONS ON S-EXPRESSIONS

         S-Expression Building Functions

         (TCONC PTR X)

         TCONC is useful for building a list by adding elements one at
         a time at the end.   This could be done with NCONC.  However,
         unlike NCONC, TCONC does not have to search to the end of the
         list  each  time it  is  called.   It  does this by keeping a
         pointer to the end of the list being assembled,  and updating
         this   pointer   after  each  call.    The  savings   can  be
         considerable for long lists.   The  cost  is  the  extra word
         required for  storing both  the list being assembled, and the
         end  of the  list.   PTR  is that word: (CAR PTR) is the list
         being assembled, (CDR PTR) is (LAST (CAR PTR)).  The value of
         TCONC is PTR,  with the appropriate  modifications to its CAR
         and CDR.   Note that TCONC is a  destructive operation, using
         RPLACA and RPLACD.


                (QUOTE (5 4 3 2 1)))
         ((5 4 3 2 1) 1)

         TCONC  can be initialized in two ways.   If PTR is NIL, TCONC
         will make up a ptr.   In this case, the program must set some
         variable to the value of the first call to TCONC.  After that
         it is unnecessary to reset since TCONC physically changes PTR

         *(SETQ FOO (TCONC NIL 1))
         ((1) 1)
                (QUOTE (4 3 2 1)))

                                      5 . 1

         ((1 4 3 2 1) 1)

         If PTR is initially (NIL),  the value of TCONC is the same as
         for PTR=NIL, but TCONC changes PTR, e.g.

         *(SETQ FOO (NCONS NIL))
                (QUOTE (5 4 3 2 1)))
         ((5 4 3 2 1) 1)

         The latter method allows  the program to initialize, and then
         call TCONC without having to perform SETQ on its value.


         Where TCONC  is  used to add elements at  the end of  a list,
         LCONC is used for building a list by adding lists at the end.
         For example:

         *(SETQ FOO (NCONS NIL))
         *(LCONC FOO (LIST 1 2))
         ((1 2) 2)
         *(LCONC FOO (LIST 3 4 5))
         ((1 2 3 4 5) 5)
         *(LCONC FOO NIL)
         ((1 2 3 4 5) 5)

         Note that  LCONC uses  the same pointer  conventions as TCONC
         for eliminating searching to the end of the list, so that the
         same pointer can be given to TCONC and LCONC interchangeably.

         *(TCONC FOO NIL)
         ((1 2 3 4 5 NIL) NIL)
         *(LCONC FOO (LIST 3 4 5))
         ((1 2 3 4 5 NIL 3 4 5) 5)

                                      5 . 2

 S-Expression Transforming Functions

 (NTH X N)

         The  value of NTH  is  the tail of X beginning  with  the Nth
         element, e.g. if N=2, the value is (CDR X), if N=3, (CDDR X),
         etc.   If  N=1,  the value is X, if N=0, for consistency, the
         value is (CONS NIL X).


         Removes all  top  level  occurrences  of X  from  the list L,
         giving  a COPY of L with all  top level elements  EQUAL  to X


         The  value of  COPY is a  copy of X.   COPY is equivalent to:
         (SUBST 0 0 X).


         Like SUBST except X  is substituted as a segment.   Note that
         if X is NIL, LSUBST returns a copy of Z with all Y's deleted.
         For example:


                                      5 . 3

 S-Expression Modifying Functions

      All  these   functions  physically  modify  their  arguments  by
 changing appropriate CAR's and CDR's.


         Similar to REMOVE, but uses EQ instead of EQUAL, and actually
         modifies the list  L  when removing  X, and thus does not use
         any additional storage.  More efficient than REMOVE.

         NOTE:  If X = (L ...   L)  (i.e.  a list of any length all of
         whose top level elements are EQ to L) then the value returned
         by (DREMOVE X  L)  is  NIL,  but even  after  the destructive
         changes to  X  there  is  still one  CONS  cell  left  in the
         modified list  which cannot  be  deleted.   Thus  if  X  is a
         variable and  it is possible that the result of (DREMOVE X L)
         might  be  NIL the user must set the  value  of  the variable
         given to DREMOVE to the value returned by the function.


         The  value  of  (DREVERSE L)  is  EQUAL  to  (REVERSE L), but
         DREVERSE destroys the original list  L and thus does  not use
         any additional storage.  More efficient than REVERSE.


         Similar  to SUBST,  but  uses  EQ and does  not  copy  Z, but
         changes the list structure Z itself.  DSUBST substitutes with
         a copy of X.  More efficient than SUBST.

                                      5 . 4

 Mapping Functions with Several Arguments

      All  of the  map functions  have  been extended to  allow called
 functions which need more than one  argument.   The function FN to be
 called is still the first argument.   Arguments 2 thru N (N <  7) are
 used  as arguments 1 thru N-1 for FN.   If  the  arguments to the map
 functions are of unequal length, the map function terminates when the
 shortest list  becomes NIL.   The  functions  behave the same  as the
 previous definitions of the functions when used with two arguments.

 Example:  This  will set the values of  A,  B and C  to  1,  2 and 3,

 * (MAPC (FUNCTION SET) (QUOTE (A B C)) (QUOTE (1 2 3)))


                                      5 . 5

 Mapping Functions Which Use NCONC

      The functions MAPCON and MAPCAN produce lists by NCONC to splice
 together  the  values  returned  by  repeated  applications  of their
 functional argument.

      MAPCON and MAPCAN are especially useful in  the  case  where the
 function returns  NIL.   Since NIL does not affect a list if NCONC'ed
 to  it,  the  output from that function does not appear in the result
 returned from MAPCON or  MAPCAN.   For example,  a function to remove
 all of the vowels from a word can be easily written as:


 where VOWELTEST is  a procedure which  takes one  argument,  LET, and
 returns NIL if LET is a vowel, and (LIST LET) otherwise.


         MAPCON calls the function FN to the list ARG.   It then takes
         the CDR of ARG and applies FN to it.  It continues this until
         ARG is NIL.   The  value  is each of the lists returned by FN
         NCONC'ed together.

 For a single list MAPCON is equivalent to:
            (COND ((NULL ARG) NIL)
                  (T (NCONC (FN ARG)
                            (MAPCON FN (CDR ARG))))))



 (1 2 3 4 2 3 4 3 4 4)


         MAPCAN is similar to MAPCON except it calls  FN with  the CAR
         of ARG instead of the whole list.

                                      5 . 6

 S-Expression Searching and Substitution Functions


         ALST is a list of pairs ((U1 .  V1) (U2 .  V2) ...
         (Un .   Vn)) with each Ui atomic.  The value of SUBLIS is the
         result  of substituting each V  for  the  corresponding  U in


 *(SUBLIS (QUOTE ((A . X) (C . Y))) (QUOTE (A B C D)))
 (X B Y D)

         New structure is created only if needed, e.g. if there are no
         substitutions, value is EQ to EXPR.


         Similar to SUBLIS except that elements of NEW are substituted
         for corresponding atoms of OLD in EXPR.


 (X B Y D)

 Note:  SUBLIS and SUBPAIR do not substitute copies of the appropriate
 expression, but substitute the identical structure.


         Similar to ASSOC, but uses EQUAL instead of EQ.

                                      5 . 7


         Y must be a tail of X, i.e. EQ to the result of applying some
         number of CDRs to X.  LDIFF gives a list of all elements in X
         but not  in Y,  i.e.,  the list difference of  X and Y.  Thus
         (LDIFF X (MEMB FOO X))  gives all elements  in  X  up  to the
         first FOO.

         Note that the value  of LDIFF is  always  new  list structure
         unless Y=NIL, in which case (LDIFF X NIL) is X itself.

         If Y is not  a tail of X,  LDIFF generates  an  error.  LDIFF
         terminates on a NULL check.

                                      5 . 8

 Efficiently Working with Atoms as Character Strings


 (NTHCHAR X N) = (CAR (NTH (EXPLODEC L) N))              if N>0
               = (CAR (NTH (REVERSE (EXPLODEC L)) N))    if N<0
               = NIL if (ABS N) = 0 or > (FLATSIZEC L)

 Note:  The  above  functions  do not  really  perform  the operations
 listed.  They actually use far more efficient methods that require no
 CONSes, but the effects are as given.


         CHRVAL  returns  the   ASCII  representation   of  the  first
         character of the print name of X.

                                      5 . 9

                            NEW PREDICATES

 Data Type Predicates


         The value of CONSP is X iff X is not an atom.
         CONSP is equivalent to:

                   (LAMBDA (X) (COND ((NOT (ATOM X)) X)))
                   (LAMBDA(X) (NOT (ATOM X)))

 Examples:       (CONSP T)       = NIL
                 (CONSP 1.23)    = NIL
                 (CONSP (QUOTE (X Y Z))) = T
                 (CONSP (CDR (QUOTE (X))))       = NIL


         The value of STRINGP is T iff X is a string.


         The  value of PATOM  is T iff  X is an atom or X is a pointer
         outside of free storage.


         The value of LITATOM  is  T iff X is a literal atom, i.e., an
         atom but not a number.

                                      6 . 1

 Alphabetic Ordering Predicate


         The  value of LEXORDER is T iff X  is  lexically less than or
         equal to  Y.   Note: Both arguments must be atoms and numeric
         arguments are all lexically less than symbolic atoms.

 Examples:       (LEXORDER (QUOTE ABC) (QUOTE CD))       = T
                 (LEXORDER (QUOTE B) (QUOTE A))          = NIL
                 (LEXORDER 123999 (QUOTE A))             = T
                 (LEXORDER (QUOTE B) (QUOTE B))          = T

                                      6 . 2

 Predicates that Return Useful Non-NIL Values


         MEMBER is the same  as  the old MEMBER except that it returns
         the tail of Y starting at the position where X is found.


         (MEMBER (QUOTE (C D)) (QUOTE ((A B)(C D)E)))
                                         = ((C D) E)
         (MEMBER (QUOTE C) (QUOTE C)))   = NIL


         MEMQ is the same as the old MEMQ except that  it  returns the
         tail of Y starting at the position where X is found.


         (MEMQ (QUOTE (C D)) (QUOTE ((A B)(C D)E)))      = NIL
         (MEMB (QUOTE A) (QUOTE (Q A B)))                        = (A B)


         The  value of TAILP  is X iff X is a  list and  a tail  of Y,
         i.e., X is EQ to some number of CDRs & 0 of Y.

 (AND X1 X2 ... Xn)      = Xn if all Xi are non-NIL
                         = NIL otherwise

 (OR X1 X2 ... Xn)       = The first non-NIL argument
                         = NIL if all Xi are NIL

 As with the  old AND and  OR these functions only evaluate as many of
 their arguments as necessary to determine the answer (e.g.  AND stops
 evaluation after the first NIL argument).

                                      6 . 3

 Other Predicates

 (NEQ X Y)

         The value of NEQ is T iff X is not EQ to Y.
         NEQ is equivalent to:

                   (LAMBDA(X Y) (NOT (EQ X Y)))

 Examples:       (NEQ T T)       = NIL
                 (NEQ T NIL)     = T
                 (NEQ (QUOTE A) (QUOTE B))       = T
                 (NEQ 1 1.0)     = T
                 (NEQ 1 1)       = NIL
                 (NEQ 1.0 1.0)   = T

                                      6 . 4

                         NEW NUMERIC FUNCTIONS

 Minimum and Maximum

 (*MIN X Y)              = Minimum of X and Y

 (MIN X1 X2 ... Xn)      = Minimum of X1, X2, ... , Xn

 (*MAX X Y)              = Maximum of X and Y

 (MAX X1 X2 ... Xn)      = Maximum of X1, X2, ... , Xn


         INUMP returns X iff X is an INUM.  It returns NIL otherwise.


         NUMTYPE  returns  FIXNUM  if  the  number  X is a fixed point
         number and FLONUM if it is a floating point number.

                                      7 . 1

         FORTRAN Functions in LISP

              It is now possible to  use the FORTRAN Math Functions in
         LISP.   This  allows the user  to  perform  computations that
         previously were  difficult  to  do  in  LISP.   All functions
         return  FLONUMs for values but may have  either a FLONUM or a
         FIXNUM for an argument.

              To  load the Arithmetic Package execute the following at
         the top level of LISP:

                         *(INC(INPUT SYS: (ARITH.LSP)))
                         <SEQUENCE OF OUTPUT>
                         <LOADER TYPES BACK>

              The above will load the Arithmetic Package into expanded
         core.   To  load the package into BINARY  PROGRAM  SPACE type
         (LOAD T) instead of (LOAD).

                         Available Functions

                 Function Name       Meaning

                     SIN             Sine with argument in radians
                     SIND            Sine with argument in degrees
                     COS             Cosine with argument in radians
                     COSD            Cosine with argument in degrees
                     TAN             Tangent
                     ASIN            Arc Sine
                     ACOS            Arc Cosine
                     ATAN            Arc Tangent
                     SINH            Hyperbolic Sine
                     COSH            Hyperbolic Cosine
                     TANH            Hyperbolic Tangent
                     LOG             Log base e
                     EXP             Take e to a power
                     SQRT            Square Root
                     FLOAT           Convert to a FLONUM
                     RANDOM          Generates a random number
                                     between 0.0 and 1.0

                                      7 . 2


 Loading Compiled Code into the High Segment

      The UCI LISP  System has  a  sharable  high segment.   This high
 segment contains the interpreter,  EDITOR,  BREAK package, and all of
 the utility functions.  If the user wants to create his own system he
 must be able  to load compiled code into  the high segment.  To allow
 the loading of code into the high segment, the user must both own the
 file and have write priveleges; to be write priveleged, the user must
 either be creating  the system from UCILSP.REL  (see  the  section on
 creating  the  system)  or  follow  the  procedure  indicated  in the
 function SETSYS.   The following three functions  are for the purpose
 of loading code into the high segment and will only  work if the user
 is write priveleged.


         If X=NIL the  "read-only"  flag is turned on (it is initially
         on) and HGHCOR returns T.  Otherwise X is the amount of space
         needed  for  compiled  code.   The  space  is  then allocated
         (expanding core if necessary), the "read-only" flag is turned
         off and HGHCOR returns T.


         If X=NIL the address of the first unused location is returned
         as  the value of  HGHORG.  Otherwise the address of the first
         unused  location is set to  X and  the  old value of the high
         seg. origin is returned.


         The  value of  HGHEND  is  the  address  of  the  last unused
         location in the high seg.

                                      8 . 1


         SETSYS  enables the user to  create  his own sharable system.
         DEVICE is either a project-programmer number or a device name
         followed by a colon (i.e.   DSK:).   FILE is the name  of the
         system the user is  creating.  In order to create the system,
         the user must Control-C out and do an SSA FILE,  then run the
         system.   After this procedure, the user has write priveleges
         and may load code into the sharable high segment.  (Note that
         the user need not use this to save a low segment only).  This
         procedure is not necessary for generating the system.

                                    8 . 1 . 1

 The Compiler and LAP

 Special variables

      In order to  print variable bindings in the backtraces,  we have
 put a pointer to thje atom header in the CAR of  the SPECIAL  cell of
 all  bound atoms  not used free in compiled code.  Unfortunately, for
 compiled code code  to  fun,  the  CAR  of  the  SPECIAL cell of free
 variables  must  be  NIL.   This,  when  loading  LAP  code,  special
 variables  must be  saved if they  are to  be printed  properly  in a
 backtrace.   The  necessary information  is  stored  on  LAPLST which
 contains the name and the special  cell  of each  special variable in
 the system.   Since this means a two word  overhead for  each special
 variable,  there is a  flag which controls  the  adding  of  items to
 LAPLST.   Special  variables are  added  to  LAPLST  iff the variable
 SPECIAL is non-NIL.  The initial value of SPECIAL is T.

 Removing Excess Entry Points - NOCALL Feature

      If,   during  compilation,  a  function  has  a  non-NIL  NOCALL
 property,  all calls  to that function are compiled as direct PUSHJ's
 to  the entry point of that function with no  reference  to  the atom
 itself.   After  loading,  all functions used in  this manner will be
 left as a list on the variable REMOB.  This means that many functions
 which  are  not major entry points can often times be REMOBed to save
 storage.   The  user  may use  (NOCALL  FOO1 FOO2 ...   FOOn) to make
 several NOCALL declarations.   Like  SPECIAL and DECLARE, when NOCALL
 is used outside of the compiler, it acts the same an NILL.

                                      8 . 2

 Miscellaneous Useful Functions


         UNBOUND returns the un-interned atom UNBOUND which the system
         places  in  the  CDR of an  atom's  SPECIAL  (VALUE)  cell to
         indicate that the atom currently has no  assigned  value even
         though it has a SPECIAL (VALUE) cell on its property list.


         Re-initializes LISP to read the user's INIT.LSP file  when it
         returns to the top level,  e.g. by a Control-G or a START, or
         a REENTER.   SYSCLR also resets the  garbage  collection time
         indicator to 0 and the CONSes  performed  indicator to 0.  It
         also performs an EXCISE.


         INITFL is an FSUBR  that sets up the file list for the user's
         INIT  file.   FILELST may  consist  of  more  than  one file.
         However,  if there is more  than  one file  in  the list, the
         files following the first one must be found or an  error will
         be generated.   The  first file in the list is optional.  The
         INIT file is initially INIT.LSP.  INITFL returns the old file
         list as its result.


         *(INITFL (INIT1 . LSP) (MYFILE . LSP) FOO)

         ((INIT . LSP))

                                      8 . 3


      The following  two functions  can  catastrophically  destroy the
 garbage collector by  creating  a circle in the free list if they are
 used to return to the free list any words which are still in use.  Do
 not use these  functions  unless you are  certain what you are doing.
 (They are  only useful in  rare cases where a small amount of working
 storage is needed by a routine which is called quite often.)


         FREE returns  the word X to the free storage list and returns


         FREELIST returns  all of the words on  the  top  level of the
         list  X to  the free storage list  and returns NIL.  FREELIST
         terminates on a NULL check.

                                    8 . 3 . 1

 New Symbol Table Functions

 The  functions in  this section are similar to the currently existing
 symbol  table  functions  except  that  they  either  strip  off (for
 storing)  or add on the  atom  relocation.  This allows MACRO code to
 use  the atom relocation register S to refer to free storage and thus
 allow  expansion  of binary program  space without  destroying LOADed
 code.   They  operate in  exactly  the  same  manner  as  their older
 counterparts.   An  error is generated if  the arguments or returning
 value is not a true cons cell.


         *RPUTSYM puts VAL - relocation in the symbol table under SYM.

 (RPUTSYM X1 X2 ...)

         RPUTSYM functions in the same manner as PUTSYM, i.e. if Xn is
         an atom,  then Xn is placed in the symbol table with  Xn less
         the relocation as it's value.   Otherwise (EVAL (CADR XN)) is
         placed in the symbol table as the value of (CAR XN).


         *GETSYM  gets  the  value  of  the  symbol  X,  adds  on  the
         relocation and returns the cell pointed to as it's value.

 (GETSYM P S1 S2 ...)

         GETSYM searches the symbol table for the symbol Sn and places
         the relocated value on the property list of Sn under property

                                    8 . 3 . 2

 Initial System Generation

 1) To Generate UCILSP.REL

    .R MACRO

    (Needs to be done only when UCILSP.MAC is changed.)

 2) To Generate the LISP System (LISP.SHR and LISP.LOW)

    .CORE 15
    FULL WORD SP. = 750
    BIN. PROG. SP. = 5

 <The preceeding loads the following files:

 (Needs to be done whenever any of the above files are changed.)

 (If during the course of the above the message "NO FW STORAGE LEFT"
 appears, experiment with variations in the allocation for Full
 Word Space.)


    .RU LO52A    (Version 52 of the DEC Loader.
                  This file is included with the LISP System)

    (Must be done whenever Step 1 is performed.)

                                      8 . 4


    .R LISP 36
    FULL WORD SP. = 2000
    BIN. PROG. SP. = 15000
    *(NOUUO NIL)

    (Must be done whenever Step 3 is performed.)

 5) To Generate LISP.LOD, the LISP LOADER


    (Needs to be done only when LOADER.MAC is changed.)

                                      8 . 5


    The Contents of the Context Stack

         Whenever a  form is given to EVAL,  it is pushed onto the top
    of the Special  Pushdown  List  in the form of an Eval-Blip.  This
    information is used for backtraces.  An Eval-Blip entry has NIL in
    the left  half  (see  SPDLFT)  and the form being evaluated in the
    right half (see SPDLRT).

         Also,  variable  bindings  are  saved on the Special Pushdown
    List.   The left  side  of the  entry contains  a  pointer  to the
    special cell and the  right  side  contains  the  value  which was

         The only other items on the Special Pushdown List are used by
    the LISP interpreter,  and always have a non-NIL atom  in the left

         In the user's programs, stack pointers are always represented
    as INUMs.   This allows the program to easily modify them with the
    standard arithmetic functions so that a program can step either up
    (toward the most recent Eval-Blip)  or down (toward the  top level
    of the interpreter) of the stack at will.

         All of the  functions in this  chapter  take  INUM's  for the
    pointer  arguments.   The  actual  pointer  to  the  stack element
    requires an offset from the beginning of the stack.   For the user
    to  obtain a  true LISP pointer he must  call  the function STKPTR
    (with  an INUM argument also).  (i.e.  if the user wishes to do an
    RPLACA or RPLACD on an element of the stack, he must get a pointer
    via STKPTR.)

                                      9 . 1

    Examining the Context Stack


         The value of SPDLPT is a stack pointer to the current  top of
         the stack.  (Returns an INUM).


         The value  of  SPDLFT  is  the  left  side  of the stack item
         pointed to by the stack pointer P.


              The value of SPDLRT  is the right side of the stack item
         pointed to by the stack pointer P.


         The value of STKPTR is a true LISP pointer to a stack item.


         If the stack pointer  P is a  pointer  to  an  Eval-Blip, the
         value of NEXTEV  is P.   Otherwise,  NEXTEV searches down the
         stack,  starting from P,  and returns a stack pointer  to the
         first  Eval-Blip  it  finds.   If  NEXTEV  can  not  find  an
         Eval-Blip it returns NIL.


         PREVEV is similar to NEXTEV except that it moves up the stack
         instead of down it.


         The  value of STKCOUNT  is  the number of  Eval-Blips  with a
         STKNAME of  NAME occurring  between  stack  positions P-1 and
         PEND, where PEND < P.

                                      9 . 2


         If position P is not  an Eval-Blip,  the value  of STKNAME is
         NIL.   If position P is an Eval-Blip and  the form is atomic,
         then  the  value of  STKNAME is  that atom.   If the  form is
         non-atomic,  STKNAME returns  the CAR  for the form, i.e. the
         name of the function.


         The value of STKNTH is a  stack pointer to  the Nth Eval-Blip
         starting  at position P.   If N is positive,  STKNTH moves up
         the stack, and if N is negative, STKNTH moves down the stack.


         The  value  of  STKSRCH  is  a  stack  pointer  to  the first
         Eval-Blip  with  a  STKNAME  of  NAME.   The direction of the
         search is  controlled  by FLAG.   If FLAG=NIL,  STKSRCH moves
         down  the  stack.   Otherwise  STKSRCH  moves  up  the stack.
         STKSRCH  never returns  P for its value,  i.e.  it steps once
         before checking for NAME.


         The value of  FNDBRKPT is a stack pointer to the beginning of
         the Eval-Block that P is in.   The  beginning of a Eval-Block
         is defined as an  Eval-Blip which  does not contain  the next
         higher Eval-Blip within it.   This function  is  used  by the
         backtrace functions.

                                      9 . 3

 Controlling Evaluation Context


         OUTVAL  adjusts  P  to  an Eval-Blip  and  returns  from that
         position with V.


         SPREDO  adjusts P to an  Eval-Blip and re-evaluates from that


         SPREVAL evaluates its argument v in its local context  to get
         a form, and then it returns to the context specified by P and
         evaluates  the  form  in that  context,  returning  from that
         context  with  the  value.   This is  very similar  to SPREDO
         except that the EVAL-blip on the stack is changed.

 Note:  OUTVAL,  SPREDO  and SPREVAL  all use NEXTEV to adjust P to an


         The value of EVALV is the value of the atom A evaluated as of
         position P.   If A is not an atom then it must be the special
         cell of an atom.   By using the special cell  instead  of the
         atom,  special variables  can be  handled properly.  EVALV is
         similar to EVAL with two arguments, but is more efficient.


         RETFROM returns VAL from the most recent call to the function
         FN with the value VAL.  For RETFROM to work, there must be an
         Eval-Blip  for  FN.   The  only  way  to be  sure  to  get an
         Eval-Blip in  compiled  code is to call the function  with no
         arguments inside of an ERRSET, e.g.  (ERRSET (FUNC)).

                                      9 . 4

                          Storage Allocation

      When  the LISP  system  is run  with a  core specification given
 (i.e.,  ".R  LISP n",  n>22),  LISP types "ALLOC?  (Y OR N)".  If you
 type  "N"  or  space  (for  no)  then  the  system  uses  the current
 allocations.  If you type "Y" (for yes) then the system allows you to
 specify for  each area  either an  octal  number followed by  a space
 designating  the  number of  words to added to that  area, or a space
 designating an increase of zero words.

 Example: (user input is underlined)

          ALLOC? (Y OR N) Y
          FULL WORD SP. = 200
          BIN. PROG. SP. = 2000
          REG. PDL. =
          SPEC. PDL. = 1000

 Any remaining storage is divided between the spaces as follows:

 1/16 for full word space,
 1/64 for each push down list,
 the remainder to free storage and bit tables.

 Reallocation of Storage

      If you  exhaust one of  the  storage  areas  it  is  possible to
 increase  the size of  that area  by using the reallocation rocedure.
 First, expand core with the time sharing system command CORE and then
 reenter LISP with the REE command.  For example, if the original core
 size was 22K, you could increase it by 4K as follows:

 .CORE 26

 When  you  reenter LISP, the same allocation procedure is followed as
 described above.

                                     10 . 1

 Initial Allocations

      The  following  are  the  initial  allocations  for  the various
 storage areas when LISP is initially run.

          FREE STORAGE    = 2200
          FULL WORD SP.   =  700
          BIN. PROG. SP.  =  100
          REG. PDL.       = 1000
          SPEC. PDL.      = 1000

                                     10 . 2


 A new data type, BLOCK, has been added to UCILSP.  A BLOCK consist of
 a block  of  contiguous  storage locations  in Binary  Program Space.
 BLOCKs are  similar to arrays in that they may contain  pointers that
 are protected  from  garbage  collection,  or  their  contents may be
 ignored by the garbage collector.  They differ, however, in the means
 of access.   BLOCKs  are accessed  by  a  pointer into Binary Program
 Space and  all of  the  functions which will act on a  cons cell will
 work equally well on an element  of a  block  (except  for printing).
 BLOCKs can be used for setting  up lists that are also tables,  as in
 setting up multiple  OBLISTs.   NOTE BENE:  the value returned by the
 BLOCK functions is a true address, not a LISP number.


         GTBLK is a SUBR that returns a zeroed BLOCK of  LENGTH words.
         If GC is NIL,  then the contents of the BLOCK  are ignored by
         the garbage collector.   If GC is non-NIL  then  the contents
         are treated as pointers and the cells pointed to will  not be


         BLKLST is a SUBR that returns a pointer type  BLOCK of LENGTH
         words.  It chains the words in the BLOCK such that the CDR of
         each  word is the succeeding word.   The top level of LIST is
         then mapped into the CAR's of the block.   If  LENGTH is NIL,
         then  the  length of  the  list is used.  If (LENGTH LIST) is
         less  than LENGTH,  then  the CAR's  of  the remaindef of the
         BLOCK are  set to NIL.   If  (LENGTH  LIST)  is  greater than
         LENGTH, the list is truncated.

                                     11 . 1