 Web pdp-10.trailing-edge.com

Trailing-Edge - PDP-10 Archives - decuslib20-01 - decus/20-0004/5lisp.tty
There are no other files named 5lisp.tty in the archive.
```

SECTION 5

PRIMITIVE FUNCTIONS AND PREDICATES

5.1 Primitive Functions

car[x]                  car gives the first element of a list x,  or the
left element of a dotted pair x.  car of  NIL is
always  NIL.   For  all  other  nonlists,  e.g.,
atoms, strings,  arrays, and numbers,  the value
is  undefined (and  on some  implementations may
generate an error).

cdr[x]                  cdr gives the rest of a list (all but  the first
element).  This  is also the  right member  of a
dotted  pair.  cdr  of NIL  is always  NIL.  The
value of cdr is undefined for other nonlists.

caar[x] = car[car[x]]   All 30 combinations  of nested cars and  cdrs up
to 4 deep
cadr[x] = car[cdr[x]]   are included in the system.  All are compiled
cddddr[x] =             open by the compiler.
cdr[cdr[cdr[cdr[x]]]]

cons[x;y]               cons constructs a dotted pair of x and y.   If y
is a list, x  becomes the first element  of that
list.  To  minimize drum accesses  the following
algorithm is used in INTERLISP-10, for finding a
page on which  to put the  constructed INTERLISP
word.

cons[x;y] is placed
1)   on the page with y if y is a list and there is room;
otherwise
2)   on the page with x if x is a list and there is room;
otherwise
3)   on the same page as the last cons if there is room;
otherwise
4)   on any page with  a specified minimum of storage,  presently 16
LISP words.

conscount[]             value  is  the  number  of  conses   since  this
INTERLISP was started up.

rplacd[x;y]             Places  the pointer  y in  the  decrement, i.e.,

5.1
```
```

cdr,  of  the cell  pointed  to by  x.   Thus it
physically changes  the internal  list structure
of x,  as opposed  to cons  which creates  a new
list element.   The only way  to get  a circular
list is  by using rplacd  to place a  pointer to
the beginning of a list in a spot at the  end of
the list.

The value of rplacd is x.  An attempt  to rplacd
NIL will cause  an error, ATTEMPT TO  RPLAC NIL,
(except  for  rplacd[NIL;NIL]).   An  attempt to
rplacd any  other non-list  will cause  an error
ARG NOT LIST.

rplaca[x;y]             similar  to  rplacd,  but  replaces  the address
pointer of x, i.e.,  car, with y.  The  value of
rplaca  is x.   An  attempt to  rplaca  NIL will
cause an  error, ATTEMPT  TO RPLAC  NIL, (except
for rplaca[NIL;NIL]).  An attempt to  rplaca any
other  non-list  will cause  an  error,  ARG NOT
LIST.

Convention: Naming  a function  by prefixing  an existing  function name
with f usually indicates that the new function is a fast version  of the
old, i.e., one which has the same definition but compiles open  and runs
without any "safety" error checks.

frplacd[x;y]            Has the same  definition as rplacd  but compiles
open as  one instruction.   Note that  no checks
are made  on x, so  that a compiled  frplacd can
clobber  NIL,  producing  strange  and  wondrous
effects.

frplaca[x;y]            Similar to frplacd.

quote[x]                This is a  function that prevents  its arguments
from being  evaluated.  Its  value is  x itself,
1
e.g., (QUOTE FOO) is FOO.

kwote[x]                (LIST (QUOTE QUOTE) x),

if x=A, and y=B, then
(KWOTE (CONS x y))= (QUOTE (A . B)).

------------------------------------------------------------------------
1
Since    giving    quote    more    than    one    argument,   e.g.,
(QUOTE EXPR (CONS X Y)), is almost  always a parentheses  error, and
one that  would otherwise go  undetected, quote itself  generates an
error in this case, PARENTHESIS ERROR.

5.2
```
```

cond[c1;c2;...;ck]      The  conditional  function  of  INTERLISP, cond,
takes an  indefinite number of  arguments c1,c2,
... ck, called clauses. Each clause ci is a list
(e1i ... eni)  of n >  1 items, where  the first
element is  the predicate, and  the rest  of the
elements the consequents.  The operation of cond
can  be  paraphrased  as IF e11 THEN e21 ... en1
ELSEIF e12 THEN e22  ... en2 ELSEIF e13  ...

The  clauses  are  considered  in   sequence  as
follows: the first expression e1i of  the clause
ci is evaluated  and its value is  classified as
false (equal to NIL) or true (not equal to NIL).
If the value of e1i is true, the expressions e2i
... eni that follow  in clause ci  are evaluated
in sequence, and the value of the conditional is
the  value of  eni, the  last expression  in the
clause.  In particular,  if n=1, i.e.,  if there
is  only one  expression in  the clause  ci, the
value of  the conditional is  the value  of e1i.
(which is evaluated only once).

If e1i is false, then the remainder of clause ci
is  ignored,  and   the  next  clause   ci+1  is
considered.  If no  e1i is true for  any clause,
the value of the conditional expression is NIL.

selectq[x;y1;y2;...;yn;z]
selects a form or sequence of forms based on the
value of  its first  argument x.   Each yi  is a
list of the  form (si e1i e2i ... eki)  where si
is the selection key.  The operation  of selectq
can be paraphrased as:
IF x=s1 THEN e1i ... eki
ELSEIF x=s2 THEN ... ELSE z.

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  e1i ... eki  are  evaluated in
sequence, and  the value of  the selectq  is the
value   of   the   last   expression  evaluated,
i.e., eki.

If si is a list, the value of x is compared with
each element (not evaluated) of si, and if  x is
eq  to any  one  of them,  then e1i  to  eki are
evaluated in turn as above.

If yi  is not  selected in one  of the  two ways
described, yi+1 is  tested, etc., until  all the
y's have been tested.  If none is  selected, the
value of the selectq is the value of z.   z must
be present.

An example of the form of a selectq is:

5.3
```
```

[SELECTQ (CAR X)
(Q (PRINT FOO)
(FIE X))
((A E I O U)
(VOWEL X))
(COND
((NULL X)
NIL)
(T (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   selectq   uses   eq   for  all
comparisons.

prog1[x1;x2;...;xn]     evaluates its arguments in order, that is, first
x1, then x2, etc,  and returns the value  of its
first  argument  x1,  e.g., (PROG1 X (SETQ X Y))
sets x to y, and returns x's original value.

progn[x1i;x2i;...;xn]   progn evaluates each of its arguments  in order,
and returns  the value of  its last  argument as
its value.  progn  is used to specify  more than
one  computation  where the  syntax  allows only
one,   e.g.,   (SELECTQ ... (PROGN ...))  allows
evaluation of several expressions as the default
condition for a selectq.

prog[args;e1;e2;...;en] This  function  allows  the  user  to  write  an
ALGOL-like    program    containing    INTERLISP
expressions (forms)  to be executed.   The first
argument,  args, is  a list  of  local variables
(must be  NIL if no  variables are  used).  Each
atom in args is  treated as the name of  a local
variable  and  bound  to  NIL.   args  can  also
contain lists of the form (atom form).   In this
case, atom  is the name  of the variable  and is
bound  to  the value  of  form.   The evaluation
takes  place  before  any  of  the  bindings are
performed,  e.g.,  (PROG ((X Y) (Y X)) ...) will
bind x to the value of y and y to the (original)
value of x.

The rest of the prog is a sequence of non-atomic
statements  (forms) and  atomic symbols  used as
labels   for  go.    The  forms   are  evaluated
sequentially; the labels serve only  as markers.
The two  special functions  go and  return alter
this flow  of control  as described  below.  The
value of  the prog is  usually specified  by the

5.4
```
```

function  return.   If  no  return  is executed,
i.e., if the prog "falls off the end," the value
of the prog is NIL.

go[x]                   go is the function used to cause a transfer in a
prog.  (GO L) will cause the program to continue
at the label L.  A  go can be used at  any level
search  higher progs  within the  same function,
e.g.,  (PROG -- A -- (PROG -- (GO A))).   If the
prog appears,  an error is  generated, UNDEFINED
OR ILLEGAL GO.

return[x]               A return  is the  normal exit  for a  prog.  Its
argument is  evaluated and is  the value  of the
prog in which it appears.

If a go or return is executed in an interpreted function which is  not a
prog, the  go or return  will be executed  in the last  interpreted prog
entered if any, otherwise cause an error.

go or return  inside of a  compiled function that is  not a prog  is not
allowed, and will cause an error at compile time.

As a corollary,  go or return in  a functional argument, e.g.,  to sort,
will not work  compiled.  Also, since  nlsetq's and ersetq's  compile as
separate functions, a go or  return cannot be used inside of  a compiled
nlsetq or ersetq if the corresponding prog is outside, i.e.,  above, the
nlsetq or ersetq.

set[x;y]                This function sets x to y.  Its value is  y.  If
x  is  not  a  literal  atom,  causes  an error,
ARG NOT LITATOM. If x  is NIL, causes  an error,
ATTEMPT TO SET NIL.  Note that  set is  a normal
lambda-spread function, i.e., its  arguments are
evaluated  before it  is called.   Thus,  if the
value of x is c,  and the value of y is  b, then
set[x;y] would result in c having value b, and b
being returned as the value of set.

setq[x;y]               An nlambda version of set: the first argument is

5.5
```
```

2
not evaluated, the second is.  Thus if the value
of X is  C and the value  of Y is  B, (SETQ X Y)
would result in X (not C) being set to B,  and B
being returned.  If x is not a literal  atom, an
error  is generated,  ARG NOT  LITATOM. If  x is
NIL, the error ATTEMPT TO SET NIL is generated.

setqq[x;y]              Like  setq  except  that  neither   argument  is
evaluated, e.g., (SETQQ X (A B C))  sets   x  to
(A B C).

gettopval[atm]          returns top  level value of  atm from  its value
cell  (even   if  NOBIND),  regardless   of  any
intervening bindings.  Interpreted, generates an
error, ARG NOT LITATOM, if atm is not  a literal
atom.  Compiles open without any error checks.

settopval[atm;val]      Sets top level  value of atm, regardless  of any
intervening bindings, i.e., stores val  in value
cell  of  atm.   Value  is   val.   Interpreted,
generates  an  error  ATTEMPT  TO  SET  NIL,  if
atm=NIL, or  ARG NOT  LITATOM, if  atm is  not a
literal atom.   Compiles open without  any error
checks.

rpaq[x;y]               An  nlambda  function like  setq,  except always
works  on top  level value  of x,  i.e.,  on the
value cell.

rpaqq[x;y]              An  nlambda function  like setqq  for  top level
values.

rpaq and rpaqq are used by prettydef (Section 14).  Both rpaq  and rpaqq
generate errors if  x is not  a literal atom.  Both are affected  by the
value of dfnflg (Section 8).  If dfnflg = ALLPROP (and the value of x is
other than  NOBIND), instead  of setting x,  the corresponding  value is
stored on  the property list  of x under  the property VALUE.   Both are
undoable.

------------------------------------------------------------------------
2
Since setq is an  nlambda, neither argument is evaluated  during the
calling  process.  However, setq  itself  calls eval  on  its second
argument.  Note  that  as  a  result,  typing   (SETQ var form)  and
SETQ(var form)  to lispx  is equivalent:  in both  cases var  is not
evaluated, and form is.

5.6
```
```

Changing and Restoring System State

In INTERLISP, a computation can be interrupted/aborted at any  point due
to an error, or more forcefully, because a control-D was  typed, causing
that  need to  perform a  computation with  the system  in  a "different
different value for some global variable, e.g., helpflag,  dfnflg, etc.,
but want to "protect" the calling environment, i.e., be able  to restore
the  state when  the  computation has  completed.  While  errors  can be
3
"caught" by errorsets, control-D cannot.  Thus the system may be left in
its changed  state as a  result of the  computation being  aborted.  The

resetlst[resetx]       nlambda, nospread.  resetx  is a list  of forms.
resetlst sets up  an errorset so that  any reset
operations  performed by  resetsave  (see below)
are restored when  the evaluation of  resetx has
been  completed  (or  an  error  occurs,   or  a
control-D is  typed).  If  no error  occurs, the
value of resetlst is the value of the  last form
on resetx, otherwise resetlst generates an error
(after  performing the  necessary restorations).
resetlst compiles open.

resetsave[resetx]       nlambda,  nospread  function  for  use  under  a
4
resetlst.  If  car of  resetx is  atomic, resets
the  top level  value of  car of  resetx  to the
value     of    cadr     of     resetx,    e.g.,
(RESETSAVE LISPXHISTORY EDITHISTORY)  resets the
value  of  lispxhistory  to  be  edithistory and
provides for the original value  of lispxhistory
to  be  restored  when  the  resetlst  completes
operation, (or an  error occurs, or  a control-D
is typed).

If car  of resetx  is not atomic,  it is  a form
that is evaluated.  If cdr of resetsave  is NIL,
e.g.,  (RESETSAVE  (RADIX  8)),  the  form  must
return as its value its "former state",  so that

------------------------------------------------------------------------
3
i.e.,  not  conveniently.   The  program  could  of  course redefine
control-D as a  userinterrupt, check for  it, reenable it,  and call
reset or something similar.

4
resetsave can be  called when not under  a resetlst.  In  this case,
the restoration will be performed at the next RESET, i.e., control-D
or  control-C  reenter.   In other  words,  there  is  an "implicit"
resetlst at the top level in evalqt.

5.7
```
```

the  effect  of  evaluating  the  form   can  be
reversed, and the system state can  be restored,
by applying car of the form to the value  of the
form,  e.g.,  (RESETSAVE  (RADIX   8))  performs
its original  value when the  resetlst completes
by  applying  radix  to  the  value  returned by

For   functions  which   do  not   return  their
"previous setting", the restoring expression can
be specified as the value of the second argument
to resetsave,  which in  this case  is evaluated
before the first argument, e.g.,
5
[RESETSAVE(SETBRK --)(LIST(QUOTE SETBRK)(GETBRK].
will  restore the  break characters  by applying
setbrk to the value returned by  (GETBRK), which
was computed  before the (SETBRK  --) expression
was evaluated.

(RESETSAVE NIL form) is permissible.   It simply
specifies that the value of form be treated as a
restoration expression, e.g.,
(RESETSAVE NIL (LIST (QUOTE CLOSEF) FILE))  will
cause file to  be closed when the  resetlst that
the resetsave  is under  completes (or  an error
occurs or a control-D is typed).

resetsave  compiles open.   Its value  is  not a
"useful" quantity.

resetvar[var;new-value;form]
Nlambda function.   Simplified form  of resetlst
and resetsave for resetting and restoring global
variables.              Equivalent            to
(RESETLST (RESETSAVE var new-value) form), e.g.,
(RESETVAR LISPXHISTORY EDITHISTORY (FOO)) resets
lispxhistory to  the value of  edithistory while
evaluating (FOO).   resetvar compiles  open.  If
no error occurs, its value is the value of form.

resetform[form1;form2]  Nlambda function.   Simplified form  of resetlst
and resetsave for resetting a system  state when
the corresponding function returns as  its value
the    "previous    setting."    Equivalent   to
(RESETLST (RESETSAVE form1) form2),        e.g.,
(RESETFROM (RADIX 8) (FOO)).  resetform compiles
open.   If no  error  occurs, its  value  is the
value returned by form2.

------------------------------------------------------------------------
5
Note  that  the  restoration  expression  is  still  "evaluated"  by
applying its car to its cdr.

5.8
```
```

For  some  applications,  the restoration  operation  must  be different
depending  on  whether  the computation  completed  successfully  or was
aborted  by  an  error  or control-D.   To  facilitate  this,  while the
restoration operation is being  performed, the value of  resetstate will
be bound  to NIL,  ERROR, or RESET,  depending on  whether the  exit was
normal, due to an error, or reset (i.e., control-D, or  in INTERLISP-10,
control-C followed by reenter).  For example,

(RESETLST (RESETSAVE (INFILE X) (LIST '[LAMBDA (FL)
(AND (EQ RESETSTATE 'RESET) (CLOSEF FL) (DELFILE FL] X))
. forms)

will cause  X to be  closed and  deleted only if  a control-D  was typed
during the execution of forms.

For  convenience in  specifying complicated  restoring  expressions, the
variable oldvalue is bound to  the value of the saving  expression.  For
example,

6
(RESETLST (RESETSAVE (INPUT FL) '(AND RESETSAVE (INPUT OLDVALUE)))
. forms)

will restore the primary input file if an error or control-D occurs.

In addition,  the function resetundo,  in conjunction with  resetlst and
resetsave, provides a way of  specifying that the system be  restored to
its  prior  state  by  undoing  the  side  effects  of  the computations
performed under  the resetlst.  Undoing  and resetundo are  described in
Section 22.

5.2 Predicates and Logical Connectives

atom[x]                 is T if x is an atom; NIL otherwise.

litatom[x]              is T if x is  a literal atom, i.e., an  atom and
not a number, NIL otherwise.

numberp[x]              is x if x is a number, NIL otherwise.

Convention: Functions that end  in p are usually predicates,  i.e., they
test for some condition.

------------------------------------------------------------------------
6
Without using oldvalue, the user would have to write
(RESETLST
(SETQ TEM (INPUT FL))
(RESETSAVE NIL (LIST  '(LAMBDA (FL) (AND  RESETSTATE (INPUT
FL)))
TEM))
forms)

5.9
```
```

7
stringp[x]              is x if x is a string, NIL otherwise.

arrayp[x]               is x if x is an array, NIL otherwise.

listp[x]                is x if x is a list-structure, i.e., one created
by one or more conses; NIL otherwise.

Note that  arrays and  strings are not  atoms, but  are also  not lists,
i.e., both  atom and  listp will  return NIL  when given  an array  or a
string.

nlistp[x]               not[listp[x]]

eq[x;y]                 The value of eq is T, if x and y are pointers to
the same structure in memory, and NIL otherwise.
eq is compiled open by the compiler.   Its value
is not guaranteed T for equal numbers  which are
not small integers. See eqp.

neq[x;y]                The value of neq is T, if x is not eq to  y, and
NIL otherwise.

null[x]                 eq[x;NIL]

not[x]                  same as null, that is eq[x;NIL].

eqp[x;y]                The value of eqp is  T if x and y are  eq, i.e.,
pointers to the same structure in memory,  or if
8
x and y are numbers and are equal in value.  Its
value is NIL otherwise.

equal[x;y]              The value of equal is  T (1) if x and y  are eq,
i.e., pointers to the same structure  in memory;
or (2) eqp,  i.e., numbers with equal  value; or
(3) strequal, i.e., strings containing  the same
sequence of characters; or (4) lists and  car of

------------------------------------------------------------------------
7
For other string functions, see Section 10.

8
For more discussion of  eqp and other number functions,  see Section
13.

5.10
```
```

x is equal to car of y, and cdr of x is equal to
9
cdr of y.  The value of equal is  NIL otherwise.
Note that x and y do not have to be eq.

equaln[x;y;depth]       like  equal, except  if depth  of  car recursion
plus  depth  of  cdr  recursion  exceeds  depth,
assumes  equality  and does  not  search further
along         that          chain,         e.g.,
equaln[(((A)) B);(((Z)) B);2]=T.   For  use with
(possibly) circular structures.

and[x1;x2;...;xn]       Takes   an   indefinite   number   of  arguments
(including  0).  If  all of  its  arguments have
non-null value,  its value is  the value  of its
last    argument,    otherwise    NIL.     e.g.,
and[x;member[x;y]] will have as its value either
NIL or a tail of y.  and[]=T.   Evaluation stops
at the first argument whose value is NIL.

or[x1;x2;...;xn]        Takes   an   indefinite   number   of  arguments
(including 0).  Its  value is that of  the first
argument whose value  is not NIL,  otherwise NIL
if   all  arguments   have  value   NIL.   e.g.,
or[x;numberp[y]]  has its  value x,  y,  or NIL.
or[]=NIL.    Evaluation  stops   at   the  first
argument whose value is not NIL.

every[everyx;everyfn1;everyfn2]
Is T  if the result of applying everyfn1 to each
element in everyx is true, otherwise NIL.
e.g., every[(X Y Z); ATOM]=T.

every        operates        by        computing
10
everyfn1[car[everyx]].    If  this  yields  NIL,
every immediately returns NIL.  Otherwise, every
computes  everyfn2[everyx],  or  cdr[everyx]  if
everyfn2=NIL, and uses this as the "new" everyx,
and     the     process     continues,     e.g.,
every[x;ATOM;CDDR]  is   true  if   every  other
element of x is atomic.

every compiles open.

------------------------------------------------------------------------
9
A loose description of equal might be to say that x and y  are equal
if they print out the same way.

10
Actually, everyfn1[car[everyx];everyx]  is computed, so  for example
everyfn1 can look at the next element on everyx if necessary.

5.11
```
```

some[somex;somefn1;somefn2]
value is  the tail of  somex beginning  with the
first element that satisfies somefn1,  i.e., for
which somefn1 applied  to that element  is true.
Value  is  NIL  if  no  such  element  exists.
e.g., some[x;(LAMBDA (Z) (EQUAL Z Y))]        is
equivalent   to   member[y;x].    some  operates
analogously     to     every.     At each stage,
somefn1[car[somex];somex]  is  computed,  and if
this is not NIL, somex is returned as  the value
of some.  Otherwise, somefn2[somex] is computed,
or cdr[somex] if  somefn2=NIL, and used  for the
next somex.

some compiles open.

notany[somex;somefn1,somefn2]
same as not[some[somex;somefn1;somefn2]]

notevery[everyx;everyfn1;everyfn2]
not[every[everyx;everyfn1;everyfn2]]

memb[x;y]               Determines if x is a member of the list y, i.e.,
if there is an element of y eg to x.  If so, its
value is  the tail of  the list y  starting with
that element. If not, its value is NIL.

fmemb[x;y]              Fast  version of  memb that  compiles open  as a
five  instruction  loop, terminating  on  a NULL
check.   Interpreted,  fmemb  gives   an  error,
BAD ARGUMENT - FMEMB,  if y  ends in  a non-list
other than NIL.

member[x;y]             Identical  to  memb except  that  it  uses equal
instead of eq to check membership of x in y.

The reason for the existence of both memb and member is that eq compiles
as one instruction but equal requires a function call, and  is therefore
considerably more expensive.   Wherever possible, the user  should write
(and use) functions that use eq instead of equal.

tailp[x;y]              Is x, if x is a tail of y, i.e., x is eq to some
11
number  of cdrs  > 0    1 of  y, we  say x  is a
proper tail.> of y, NIL otherwise.

------------------------------------------------------------------------
11
If x is eq to some number of cdrs

5.12
```
```

assoc[key;alst]         alst is a list of lists (usually  dotted pairs).
The value of assoc is the first sublist  of alst
whose car is eq to  key.  If such a list  is not
found, the value is NIL.  Example:
assoc[B;((A . 1) (B . 2) (C . 3))] = (B . 2).

fassoc[key;alst]        Fast version of assoc that compiles open as  a 6
instruction loop,  terminating on a  NULL check.
Interpreted, fassoc gives an error if  alst ends
in  a non-list  other than  NIL, BAD  ARGUMENT -
FASSOC.

sassoc[key;alst]        Same as assoc but uses equal instead of eq.

putassoc[key;val;alst]  Searches alst for an element car of which  is eq
to key.  If one is found, cdr is replaced (using
rplacd) with val.  If no such element  is found,
cons[prop;val]  is  added at  the  end  of alst.
Value is ?.  If alst is NIL, generates an error,
ATTEMPT TO RPLAC NIL.  Otherwise, if alst is not
a list, generates an error, ARG NOT LIST.

listget[lst;prop]       Similar  to  getprop (Section  7)  but  works on
lists using property list format.   Searches lst
two elements at  a time, i.e., by  cddr, looking
for an  element eq  to prop.   If one  is found,
returns the next element of lst,  otherwise NIL.
Generates an ARG NOT LIST  error if lst  is non-
NIL and not a list.

listput[lst;prop;val]   Similar  to  putprop.   Searches  lst   by  cddr
looking for  prop.  If  prop is  found, replaces
the next  element of  lst with  val.  Otherwise,
prop and val are added to the end of lst.  Value
is ?.  Generates an ARG NOT LIST error if lst is
not a list.

listget1[lst;prop]      Like listget but searches lst one cdr at a time,
i.e., looks at each element.

listput1[lst;prop;val]  Like listput  except searches lst  one cdr  at a
time.

5.13
```