perm filename MACLSP.DBA[UP,DOC] blob
sn#239461 filedate 1976-10-03 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00157 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00017 00002
C00019 00003 General Information
C00023 00004 LISP/MACLISP Reference Manual
C00028 00005 General Information
C00031 00006 LISP/MACLISP Reference Manual
C00032 00007 Data
C00037 00008 LISP/MACLISP Reference Manual
C00043 00009 Data
C00047 00010 LISP/MACLISP Reference Manual
C00050 00011 Data
C00053 00012 LISP/MACLISP Reference Manual
C00055 00013 The Basic Processes of LISP
C00057 00014 LISP/MACLISP Reference Manual
C00060 00015 The Basic Processes of LISP
C00065 00016 LISP/MACLISP Reference Manual
C00070 00017 The Basic Processes of LISP
C00072 00018 LISP/MACLISP Reference Manual
C00075 00019 The Basic Processes of LISP
C00078 00020 LISP/MACLISP Reference Manual
C00082 00021 The Basic Processes of LISP
C00086 00022 LISP/MACLISP Reference Manual
C00090 00023 The Basic Processes of LISP
C00092 00024 LISP/MACLISP Reference Manual
C00093 00025 Functions for Manipulating List Structure
C00095 00026 LISP/MACLISP Reference Manual
C00098 00027 Functions for Manipulating List Structure
C00102 00028 LISP/MACLISP Reference Manual
C00105 00029 Functions for Manipulating List Structure
C00108 00030 LISP/MACLISP Reference Manual
C00109 00031 Functions for Manipulating List Structure
C00111 00032 LISP/MACLISP Reference Manual
C00114 00033 Functions for Manipulating List Structure
C00117 00034 LISP/MACLISP Reference Manual
C00120 00035 Functions for Manipulating List Structure
C00124 00036 LISP/MACLISP Reference Manual
C00125 00037 Flow of Control
C00129 00038 LISP/MACLISP Reference Manual
C00133 00039 Flow of Control
C00137 00040 LISP/MACLISP Reference Manual
C00141 00041 Flow of Control
C00145 00042 LISP/MACLISP Reference Manual
C00149 00043 Flow of Control
C00150 00044 LISP/MACLISP Reference Manual
C00154 00045 Flow of Control
C00158 00046 LISP/MACLISP Reference Manual
C00161 00047 Manipulating the Constituents of Atomic Symbols
C00165 00048 LISP/MACLISP Reference Manual
C00167 00049 Manipulating the Constituents of Atomic Symbols
C00171 00050 LISP/MACLISP Reference Manual
C00174 00051 Manipulating the Constituents of Atomic Symbols
C00177 00052 LISP/MACLISP Reference Manual
C00181 00053 Manipulating the Constituents of Atomic Symbols
C00182 00054 LISP/MACLISP Reference Manual
C00186 00055 Manipulating the Constituents of Atomic Symbols
C00187 00056 LISP/MACLISP Reference Manual
C00188 00057 Functions on Numbers
C00190 00058 LISP/MACLISP Reference Manual
C00193 00059 Functions on Numbers
C00196 00060 LISP/MACLISP Reference Manual
C00197 00061 Functions on Numbers
C00200 00062 LISP/MACLISP Reference Manual
C00201 00063 Functions on Numbers
C00204 00064 LISP/MACLISP Reference Manual
C00206 00065 Functions on Numbers
C00207 00066 LISP/MACLISP Reference Manual
C00209 00067 Functions on Numbers
C00212 00068 LISP/MACLISP Reference Manual
C00214 00069 Functions on Numbers
C00216 00070 LISP/MACLISP Reference Manual
C00218 00071 Functions on Numbers
C00219 00072 LISP/MACLISP Reference Manual
C00222 00073 Character Manipulation
C00225 00074 LISP/MACLISP Reference Manual
C00229 00075 Character Manipulation
C00230 00076 LISP/MACLISP Reference Manual
C00233 00077 Character Manipulation
C00236 00078 LISP/MACLISP Reference Manual
C00237 00079 Functions Concerning Arrays
C00241 00080 LISP/MACLISP Reference Manual
C00244 00081 Functions Concerning Arrays
C00248 00082 LISP/MACLISP Reference Manual
C00250 00083 "Mapping" Functions
C00254 00084 LISP/MACLISP Reference Manual
C00258 00085 "Mapping" Functions
C00261 00086 LISP/MACLISP Reference Manual
C00262 00087 Sorting Functions
C00266 00088 LISP/MACLISP Reference Manual
C00268 00089 Functions for Controlling the Interpreter
C00271 00090 LISP/MACLISP Reference Manual
C00273 00091 Functions for Controlling the Interpreter
C00276 00092 LISP/MACLISP Reference Manual
C00280 00093 Functions for Controlling the Interpreter
C00285 00094 LISP/MACLISP Reference Manual
C00286 00095 Functions for Controlling the Interpreter
C00290 00096 LISP/MACLISP Reference Manual
C00293 00097 Functions for Controlling the Interpreter
C00296 00098 LISP/MACLISP Reference Manual
C00301 00099 Functions for Controlling the Interpreter
C00304 00100 LISP/MACLISP Reference Manual
C00309 00101 Functions for Controlling the Interpreter
C00312 00102 LISP/MACLISP Reference Manual
C00317 00103 Functions for Controlling the Interpreter
C00319 00104 LISP/MACLISP Reference Manual
C00323 00105 Functions for Controlling the Interpreter
C00326 00106 LISP/MACLISP Reference Manual
C00329 00107 Functions for Controlling the Interpreter
C00332 00108 LISP/MACLISP Reference Manual
C00335 00109 Functions for Controlling the Interpreter
C00339 00110 LISP/MACLISP Reference Manual
C00342 00111 Functions for Controlling the Interpreter
C00343 00112 LISP/MACLISP Reference Manual
C00345 00113 Functions for Controlling the Interpreter
C00349 00114 LISP/MACLISP Reference Manual
C00350 00115 Functions for Controlling the Interpreter
C00354 00116 LISP/MACLISP Reference Manual
C00358 00117 Functions for Controlling the Interpreter
C00362 00118 LISP/MACLISP Reference Manual
C00367 00119 Functions for Controlling the Interpreter
C00371 00120 LISP/MACLISP Reference Manual
C00375 00121 Functions for Controlling the Interpreter
C00378 00122 LISP/MACLISP Reference Manual
C00379 00123 Functions for Controlling the Interpreter
C00381 00124 LISP/MACLISP Reference Manual
C00385 00125 Functions for Controlling the Interpreter
C00388 00126 LISP/MACLISP Reference Manual
C00391 00127 Functions for Controlling the Interpreter
C00395 00128 LISP/MACLISP Reference Manual
C00396 00129 Functions for Controlling the Interpreter
C00399 00130 LISP/MACLISP Reference Manual
C00400 00131 Input and Output
C00404 00132 LISP/MACLISP Reference Manual
C00406 00133 Input and Output
C00411 00134 LISP/MACLISP Reference Manual
C00417 00135 Input and Output
C00421 00136
C00422 00137 .in +%undent%
C00423 00138 LISP/MACLISP Reference Manual
C00427 00139 Input and Output
C00429 00140 LISP/MACLISP Reference Manual
C00432 00141 Input and Output
C00436 00142 LISP/MACLISP Reference Manual
C00439 00143 Input and Output
C00442 00144 LISP/MACLISP Reference Manual
C00445 00145 Input and Output
C00448 00146 LISP/MACLISP Reference Manual
C00453 00147 Input and Output
C00455 00148 LISP/MACLISP Reference Manual
C00459 00149 Input and Output
C00463 00150 LISP/MACLISP Reference Manual
C00466 00151 Input and Output
C00470 00152 LISP/MACLISP Reference Manual
C00472 00153 Input and Output
C00476 00154 LISP/MACLISP Reference Manual
C00479 00155 Input and Output
C00480 00156 LISP/MACLISP Reference Manual
C00484 00157 Input and Output
C00486 ENDMK
C⊗;
***************
***************
* *
* ROUGH DRAFT *
* *
***************
***************
LISP/MACLISP Reference Manual
Dialect: MACLISP
Authors:
David A. Moon
David P. Reed
and
Ira Goldstein
Guy L. Steele
Alexander Sunguroff
**************DO NOT BELIEVE**************
*************DO NOT DUPLICATE*************
c Copyright, 1973, Massachusetts Institute of Technology
All rights reserved
General Information
***** ROUGH DRAFT #9905 *****
1. General Information
1.1 The MACLISP Language
MACLISP is a dialect of LISP developed at M.I.T.'s Project MAC for
use in artificial intelligence research and related fields. MACLISP
is descended from the commonly-known LISP 1.5 dialect, however many
features of the language have been changed or added.
This document is intended both as a reference source for the
language and as a user's guide to three implementations. These are,
in chronological order, the M.I.T. Artifical Intelligence Lab's
implentation on the DEC pdp-10 computer under their operating system
ITS, hereafter referred to as "the ITS implementation," Project MAC's
implementation on Honeywell's version of the Multics system, hereafter
referred to as "the Multics implementation," and the version that runs
on the DEC pdp-10 under DEC's TOPS-10 operating system, hereafter
called "the DEC-10 implementation." The DEC-10 implementation also
runs under TENEX by means of a TOPS-10 emulator. Since the ITS and
DEC-10 implementations are closely related, they are sometimes
referred to collectively as the pdp-10 implementation.
These implementations are mostly compatible; however, some
implementations have extra features designed to exploit peculiar
features of the system on which they run, and some implementations are
temporarily missing some features. Most programs will work on any
implementation, although it is possible to write machine-dependent
code if you try hard enough.
1.2 Structure of the Manual
This manual is not specifically designed for LISP users of any
particular level of ability, though it does make assumptions as to
what an "average" user of LISP will require of a manual. Since it is
intended for a general class of users it must satisfy some constraints
of design in order to be of benefit to a user of some particular
ability. The manual must provide as much information as a user might
need, yet provide it in a manner such that a less experienced user
might still have access to some of that information.
11/18/73 1. 1.2 Page 1
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
The general structuring of the manual is by meaning; things of
similar meaning will be found grouped together. Explanatory text and
function definitions are interspersed. Usually text will be found at
the beginnings of chapters, sections, or subsections with definitions
following. Complexity tends to increase across each subdivision of
the manual while usefulness to a new user tends to decrease. The
chapters in the beginning of the manual are of more use to a new user,
the later ones contain either more complex or less useful information.
If a chapter is undivided then it will become more complex toward the
end. If a chapter is subdivided, then each section or subsection
again follows the same criteria.
Accessing information in the manual is dependant on both the user's
level of ability and the purpose for which she or he is using the
manual. Though cover to cover reading is not recommended (though not
excluded), it is suggested that someone who has never previously seen
this manual browse through it, touching the beginning of each
subdivision that is listed in the Table of Contents, in order to
familiarize himself or herself with the material that it contains. To
find an answer to some particular question, one must use one of the
provided access methods. Since the manual is structured by meaning
one can use the Table of Contents that is found at the beginning of
the manual, to find where information of a general class will be
found. Entry into the manual by meaning is also facilitated by the
Glossary and the Concept Index which are found at the end. Also at
the end of the manual is a Function Index which is probably most
useful to a regular and repeated user of the dialect, or to an
experienced user of another dialect, who wishes to find out the answer
to a question about a specific function. However since the manual is
structured by meaning, it is useful to examine other functions in the
vicinity of the first, for usefulness.
It is again suggested that a new reader of this manual should
familiarize himself or herself with its contents.
1.3 Notational Conventions
There are some conventions of notation that must be mentioned at
this time, due to their being used in examples.
A combination of the characters, equal sign and greater then
symbol, " => ," will be used in examples of LISP code to mean
evaluation (that is the application of the function, eval.).
All uses of the phrase, "LISP reader," unless further qualified,
refer to that part of the LISP system which does input, and not to
some person.
Page 2 1. 1.3 11/18/73
General Information
***** ROUGH DRAFT #9905 *****
The two characters, accent acute, " ' ," and semi-colon, " ; ," are
examples of what are called macro characters. Though the macro
character facility, which is defined in the chapter on Input/Output,
is ot of immediate interest to a new user of the dialect, these two
come preset by the LISP system and are useful. When the LISP reader
encounters an accent accute, it reads in the next S-expression and
encloses it in a call to the function, quote. That is:
'some-atom
turns into:
(quote some-atom)
and
'(cons 'a 'b)
turns into
(quote (cons (quote a) (quote b)))
The semi-colon is used a commenting feature. When the LISP reader
encounters it, it discards the rest of that line of input.
All LISP examples in this manual are written according to the
conventions of the Multics implementation, which uses both upper and
lower case letters and spells the names of most system functions in
lower case. Some implementations of MACLISP only use upper case
letters because they run on systems which are not equipped with
terminals capable of generating and displaying the full ascii
character set. Howeverm these systems will accept input in lower case
and translate it to upper case.
11/18/73 1. 1.3 Page 3
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
This page intentionally left blank.
Page 4 1. 1.3 11/18/73
Data
***** ROUGH DRAFT #9905 *****
2. Data
2.1 Data Types
LISP works with pieces of data called "objects" or "S-expressions."
These can be simple "atomic" objects or complex objects compounded out
of other objects. Functions, the basic units of a LISP program, are
also objects and may be manipulated as data.
Objects come in several types. All types are self-evident, that is
it is possible for the system to tell what type an object is just by
looking at it, so it is not necessary to declare the types of
variables as in some other languages. It should be noted that LISP
represents objects as pointers, so that any object will fit in the
same cell, and the same object may have several different usages --
for example the same identical object may be a component of two
different compound objects.
The data-types are divided into three broad classes: the atomic
types, the non-atomic types, and the composite types. Objects are
divided into the same three classes according to their type. Atomic
objects are basic units which cannot be broken down by ordinary
chemical means, while non-atomic objects are structures constructed
out of other objects, and composite objects are indivisible entities
which have subcomponents which may be extracted and modified but not
removed.
The atomic data types are numbers, atomic symbols, strings, and
subr-objects.
In LISP numbers can be represented by three types of atomic
objects: fixnums, flonums, and bignums. A fixnum is a fixed-point
binary integer whose range of values is limited by the size of a
machine word. A flonum is a floating-point number whose precision and
range of values are machine-dependent. A bignum is an
arbitrary-precision integer. It is impossible to get "overflow" in
bignum arithmetic, as any finite integer can be represented as a
bignum. However, fixnum and flonum arithmetic is faster than bignum
arithmetic and bignums require more memory. Sometimes the word
"fixnum" is used to include both fixnums and bignums; in this manual,
however, the word "fixnum" will never include bignums unless that is
explicitly stated.
The external representations for numbers are as follows: a fixnum
is represented as a sequence of digits in a specified base, usually
octal. A trailing decimal point indicates a decimal base. A flonum
11/18/73 2. 2.1 Page 5
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
is represented as a set of digits containing an embedded or leading
decimal point and/or a trailing exponent. The exponent is introduced
by an upper or lower case "e". A bignum looks like a fixnum except
that it has enough digits that it will not fit within the range
available to fixnums. Any number may be preceded by a + or - sign.
Some examples of fixnums are 4, -1232, -191., +46. An example of a
bignum is 1565656565656565656565656565656565. Some examples of
flonums are: 4.0, .01, -6e5, 4.2e-1.
Another LISP data type is the string. This is a sequence of 0 or
more characters. Strings are used to hold messages to be typed out
and to manipulate text when the structure of the text is not
appropriate for the use of "list processing." The external
representation of a string is a sequence of characters enclosed in
double-quotes, e.g. "foo". If a " is to be included in the string, it
is written twice, e.g. "foo""bar" is foo"bar.
One of the most important LISP data types is the atomic symbol. In
fact, the word "atom" is often used to mean just atomic symbols, and
not the other atomic types. An atomic symbol has a name, a value, and
possibly a list of "properties". The name is used to refer to the
symbol in input and output. The external representation of an atomic
symbol is just its name. This name is often called the "pname," or
"print-name," as it is a sequence of characters that are printed out.
For example, an atomic symbol with a pname of foo would be represented
externally as foo; internally as a structure containing the value, the
pname "foo", and the properties.
There are two special atomic symbols, t and nil. These always have
themselves as values and their values may not be changed. nil is used
as a "marker" is many contexts; it is essential to the maintenance of
data structures such as lists. t is usually used when an antithesis
to nil is required for some purpose.
The value of an atomic symbol is any object of any type. There are
functions to set and get the value of a symbol. Because atomic
symbols have values associated with them, they can be used as
variables in programs and as "dummy arguments" in functions. It is
also possible for an atomic symbol to have no value, in which case it
is said to be "undefined" or "unbound."
The property list of an atomic symbol will be explained in section
6.2. It is used for such things as recording the fact that a
particular atomic symbol is the name of a function.
An atomic symbol with less than two characters in its pname is
often called a "character object" and used to represent an ascii
character. The atomic symbol with a zero-length pname represents the
ascii null character, and the symbols with 1-character pnames
represent the character which is their pname. Functions which take
character objects as input usually also accept a string one character
long or a fixnum equal to the ascii-code value for the character.
Page 6 2. 2.1 11/18/73
Data
***** ROUGH DRAFT #9905 *****
Character objects are always interned on the obarray (see section
6.3).
A "subr-object" is a special atomic data-type whose use is normally
hidden in the implementation. A subr-object represents executable
machine code. The functions built into the LISP system are
subr-object, as are user functions that have been compiled. A
subr-object cannot be named directly, so each system function has an
atomic symbol which serves as its name. The symbol has the
subr-object as a "property."
One composite data type is the array. An array consists of a
number of cells, each of which may contain any LISP object. The cells
of an array are accessed by subscripting. An array may have one or
more dimensions; the upper limit on the number of dimensions is
implementation-defined. An array is always associated with an atomic
symbol which is its name. This atomic symbol has on its property list
a property with the indicator 'array' and a value, called an
array-object or sometimes a "special array cell," which permits the
implementation to access the array. See chapter 9 for an explanation
of how to create, use, and delete arrays.
Another composite data type is the file-object, which is described
in chapter 13.
The non-atomic data type is the "cons." A cons is a structure
containing two components, called the "car" and the "cdr" for
historical reasons. These two components may be any LISP object, even
another cons (in fact, they could even be the same cons). In this way
complex structures can be built up out of simple conses. Internally a
cons is represented in a form similar to:
| | |
| car | cdr |
|||
where the boxes represent cells of memory large enough to hold a
pointer, and "car" and "cdr" are two pointers to objects. The
external representation of a cons is the "dotted-pair" notation
(A . B) where A is the car and B is the cdr.
Another way to write the internal representation of a cons, which
is more convenient for large structures, is:
---> o -----> cdr
|
|
V
car
11/18/73 2. 2.1 Page 7
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
There are three LISP functions associated with conses. The
function cons combines its two arguments into a cons; (A . B) can be
generated by (cons A B). The function car returns the car of its
argument, and the function cdr returns the cdr of its argument.
One type of structure, built out of conses, that is used quite
often, is the "list." A list is a row of objects of arbitrary length.
A list of 3 things A, B, and C is constructed as (cons A (cons B (cons
C nil))); nil is a special atom that is used to mark the end of a
list. The structure of a list can be diagrammed as:
---> o ----> o ----> o ----> nil
| | |
| | |
V V V
A B C
From this it can be seen that the car of a list is its first element,
that the cdr of a list is the list of its elements other than the
first, and that the list of no elements is the same as nil.
This list of A, B, and C could be represented in the dot-notation
used for conses as (A . (B . (C . nil))), however a more convenient
notation for the external representation of lists has been defined:
the "list-notation" (A B C). It is also possible to have a hybrid of
the two notations which is used for structures which are almost a list
except that they end in an atom other than nil. For example,
(A . (B . (C . D))) can be represented as (A B C . D).
A list not containing any elements is perfectly legal and
frequently used. This zero-length list is the atom nil. It may be
typed in as either nil or ().
Page 8 2. 2.1 11/18/73
Data
***** ROUGH DRAFT #9905 *****
2.2 Predicates for Checking Types
A predicate is a function which tests for some condition
involving its argument and returns t if that condition is true
and nil if it is not true. These predicates return t if their
argument is of the type specified by the name of the function,
nil if it is of some other type. Note that the name of most
predicates ends in the letter p, by convention.
atom SUBR 1 arg
The atom predicate is nil if its argument is a dotted-pair or a
list, and t if it is any kind of atomic object such as a number,
a character string, or an atomic symbol.
fixp SUBR 1 arg
The fixp predicate returns t if its argument is a fixnum or a
bignum, otherwise nil.
floatp SUBR 1 arg
The floatp predicate returns t if its argument is a flonum, nil
if it is not.
numberp SUBR 1 arg
The numberp predicate returns t if its argument is a number, nil
if it is not.
typep SUBR 1 arg
typep is a general type-predicate. It returns an atomic symbol
describing the type of its argument, chosen from the list
(fixnum flonum bignum list symbol string random)
symbol means atomic symbol. Random is for all types that don't
fit in any other category. Thus numberp could have been defined
by:
11/18/73 2.2 Page 9
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
(defun numberp (x)
(and (memq (typep x) '(fixnum flonum bignum))
x))
These two functions only exist in the Multics implementation.
stringp SUBR 1 arg
The stringp predicate returns its argument if that argument is a
string, otherwise nil.
subrp SUBR 1 arg
The subrp predicate returns t if its argument is a "subr" object,
i.e. a pointer to the machine code for a compiled or system
function. Example:
(subrp (get 'car 'subr)) => t
Page 10 2.2 11/18/73
The Basic Processes of LISP
***** ROUGH DRAFT #9905 *****
3. The Basic Processes of LISP
3.1 Binding
The way "local variables" are implemented in LISP is by a
procedure known as "binding." Local variables and global
variables are all the value of the one atomic symbol with the
pname of the name of the variable. [??what is this cruft??] When
the scope of a "local variable" is entered, the old value of the
variable is saved and it is reset to the value it will have
locally. This is "binding." When the scope of the local
variable is exited, for whatever reason, whether it is a "normal
exit" or an "abnormal exit," the variable is restored to its old
value. This is "unbinding."
Binding is used for temporary variables in prog`s and do`s,
and for binding lambda-variables ("dummy arguments") to the
values of the arguments to a function or lambda-expression.
[??how can anyone understand this??]
11/18/73 3. 3.1 Page 11
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
3.2 Evaluation
Evaluation is a transformation which takes one object, called a
form, and produces another, called the value of that form. Evaluation
is used internally by LISP in processing typed input and in
(recursively) evaluating portions of a form in the process of
evaluating that form. Evaluation is available for explicit use as the
function eval.
Evaluation is performed by the LISP interpreter, following the
rules set forth below.
Numbers and strings always evaluate to themselves.
Atomic symbols evaluate to the 'value' associated with them. It is
possible for an atomic symbol to have no value, in which case the
process of evaluation encounters an error, which is handled as
described in section 12.4. The special atomic symbols t and nil
always have themselves as values, consequently they evaluate like
numbers rather than like atomic symbols.
Random objects, such as subr-objects, files, and array-objects
evaluate to something random; often themselves. Note that an
array-object is different from an atomic symbol which is the name of
an array; such an atomic symbol is evaluated the same as any other
atomic symbol.
The evaluation of non-atomic forms is more complex. The evaluator
regards a non-atomic form as a list, whose first element (car) is a
function and whose remaining elements (cdr) are arguments. The value
of the form is the result of the function when applied to those
arguments, according to the "application" procedure described below.
Page 12 3. 3.2 11/18/73
The Basic Processes of LISP
***** ROUGH DRAFT #9905 *****
3.3 Application
"Application" is the procedure by which a function is invoked with
specified arguments to produce a value (and possibly side effects.)
The first step in application is an examination of the function.
If it is atomic, then it is required to be an atomic symbol. The
atomic symbol's property list is searched for one of the following
properties, called "functional properties":
expr, fexpr, macro, subr, fsubr, lsubr, array, autoload
If none of these is found, then the atomic symbol is evaluated and its
value is taken to be the function being called and application is
restarted at the beginning.
If an array property is found, there is a subscripted reference to
the array. The arguments are evaluated from left to right, and used
as subscripts to the array. Consequently they must be fixnums and
there must be the same number of them as there are dimensions in the
array and they must lie within the bounds of the array. The result is
the contents of the array cell specified by the subscripts.
If a subr, lsubr, or fsubr property is found, the value of the
property must be a subr-object. The subr-object represents a
machine-code subroutine, which may be a function built in to the
interpreter, a compiled LISP function, or a function written in some
other language made known to LISP by some facility such as defsubr or
lap, depending on the implementation. The evaluator calls this
subroutine, giving it the specified arguments, and the result is the
LISP object returned by the subroutine. If the subr-object was in an
fsubr property, the subroutine is called with one argument which is
the cdr of the list being evaluated. Thus the arguments are not
evaluated. If it was a subr or lsubr property, the arguments are
evaluated from left to right before they are passed to the subroutine.
A subr requires a certain fixed number of arguments, but an lsubr can
take a variable number of arguments, between two bounds which depend
on the particular lsubr. (See the args function).
If a fexpr property is found, the value of the property must be a
list whose car is the atom lambda and whose cadr is a list of one or
two atomic symbols, referred to as lambda-variables. The cddr is a
list of zero or more objects, referred to as the body. The first
lambda-variable is bound to the cdr of the form being evaluated, i.e.
to the list of unevaluated arguments. Of course, the body of the
fexpr may evaluate the arguments itself by explicitly using the
function eval. The second lambda-variable, if present, is bound to an
"a-list pointer" which represents the binding state which existed just
before the fexpr's lambda-variables were bound. After the
lambda-variables have been bound, the body of the fexpr is evaluated
from left to right. The result is the value of the last form
evaluated.
11/18/73 3. 3.3 Page 13
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
If an expr property is found, there are three cases: 1) If the
value of the property is an atomic symbol, that atomic symbol is taken
as the function and application is restarted from the beginning. 2)
If the value of the property is a list whose car is the atom lambda
and whose cadr is a list of zero or more atomic symbols, called
lambda-variables, then the evaluation is the invocation of an
interpreted function called an 'expr.' There must be the same number
of arguments as lambda-variables. The arguments are evaluated from
left to right and then the lambda-variables are bound to the values of
the arguments. Next the body of the expr is evaluated in the same way
as for a fexpr. 3) If the value of the property is a list whose car
is the atom lambda and whose cadr is an atomic symbol other than nil,
the evaluation is an invocation of an interpreted function called a
'lexpr,' which is the interpreted version of lsubr. The arguments are
evaluated from left to right and saved in a place where the functions
arg and setarg can find them. Then the single lambda-variable is
bound to the number of arguments, and the body is evaluated in the
same way as for an expr.
If a macro property is found, its value must look like the value of
a fexpr property. The difference between a macro and a fexpr is
twofold. One, the first lambda-variable is bound to the whole form,
instead of just the cdr of the form (the list of arguments). Two, the
object returned by the macro is treated as a form and re-evaluated and
its value becomes the result of the application.
If an autoload property is found, the definition of the function is
loaded in from an external file and then used. See section 12.4.4 for
details.
If the function is not an atom, it is what is sometimes called a
"functional form." Note that actually a functional form is anything
that can be applied, including atoms. One kind of functional form is
a list whose car is the atomic symbol lambda. This is often called a
"lambda" expression. It is applied exactly the same way as if the
function had been an atomic symbol which had an expr property whose
value was the lambda-expression.
Another kind of functional form is a list of the atom label, an
atomic symbol, and a functional form. The atomic symbol is bound to
the functional form, and then the functional form is applied to the
arguments. This is used for strange things like recursive
lambda-expressions. Generally a permanently-defined function is
better than a label.
The third kind of functional form is a "funarg," which can be
produced by the *function function. The funarg contains an a-list
pointer. The binding context is temporarily set to the previous
context indicated by this a-list pointer, and then the functional form
contained in the funarg is applied.
Page 14 3. 3.3 11/18/73
The Basic Processes of LISP
***** ROUGH DRAFT #9905 *****
If the functional form does not fall into any of the above cases,
it is evaluated and the value is then used as the function being
applied and application starts over again at the beginning.
In addition to the variety of application which has just been
described, which is used internally by the evaluation procedure, there
is a similar but not identical application procedure available through
the function apply. The main difference is that the function and the
arguments are passed to apply seperately. They are not consed up into
a form. Consequently macros are not accepted by this version of
application. In addition, the arguments to exprs, lexprs, subrs,
lsubrs, arrays, etc. are not evaluated, since the caller of apply is
presumed to have prepared the arguments.
11/18/73 3. 3.3 Page 15
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
3.4 A-list Pointers
There is a special type of object called an "a-list pointer" which
can be used to refer to a binding context. Due to the stack
implementation of MACLISP, an a-list pointer is only valid while
control is nested within the binding context it names. It is not
possible to exit from within a binding context but keep it around by
keeping an a-list pointer to it.
An a-list pointer is either a negative fixnum or nil. nil means
the "global" or "top level" binding context. The negative fixnum is a
special value of implementation dependent meaning which should be
obtained only from one of the three following sources: the function
evalframe, the function errframe, or the second lambda-variable of a
fexpr.
The only use for a-list pointers is to pass them to the functions
eval and apply to specify the binding context in which variables are
to be evaluated during that evaluation or application. A-list
pointers are also used internally by *function. When it generates a
funarg, it puts in the funarg the functional form it was given and an
a-list pointer designating the binding environment current at the time
*function was called.
Page 16 3. 3.4 11/18/73
The Basic Processes of LISP
***** ROUGH DRAFT #9905 *****
3.5 Functions to Perform These Processes
eval LSUBR 1 or 2 args
(eval x) evaluates x, just as if it had been typed in at top
level, and returns the result. Note that since eval is an lsubr,
its argument actually will be evaluated twice.
(eval x y) evaluates x in the binding context specified by the
a-list pointer y.
apply LSUBR 2 or 3 args
(apply f y) applies the function f to the list of arguments y.
Unless f is an fsubr or fexpr such as 'cond' or 'and' which
evaluates its arguments in a funny way, the arguments in the list
y are used without being evaluated.
Examples:
(setq f '+) (apply f '(1 2 3)) => 6
(setq f '-) (apply f '(1 2 3)) => -4
(apply 'cons '((+ 2 3) 4)) =>
((+ 2 3) . 4) not (5 . 4)
(apply f y p) works like apply with 2 arguments except that the
application is done in the binding environment specified by the
"a-list" pointer p.
quote FSUBR
Quote returns its unevaluated argument. Quote is used to include
constants in a form. For convenience, the read function normally
converts any S-expression preceded by the apostrophe (acute
accent) character into the form (quote <s-expression>). For
example, the form:
(setq x '(some list))
is converted by the reader to:
(setq x (quote (some list)))
which causes the variable x to be set to the constant list value
shown upon evaluation. For more information on input syntax, see
the detailed discussion in chapter 13.
11/18/73 3. 3.5 Page 17
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
function FSUBR
Function is like quote except that its argument is a function.
It is used when passing a functional argument. Example:
(f00 x (function (lambda (p q)
(cond ((numberp q) p)
((numberp p) q)
;or any other random function in here
(t (cons p q)) )))
y)
calls f00 with 3 arguments, the second of which is the function
defined by the lambda-expression.
Note: quote and function are completely equivalent in the
interpreter. The compiler sometimes needs function to tell it
that a lambda-expression is a function to be compiled rather than
a constant.
Function makes no attempt to solve the "funarg problem."
*function should be used for this purpose.
*function FSUBR
The value of (*function f) is a "funarg" of the function f. A
funarg can be used like a function. It has the additional
property that it contains an a-list pointer so that the values of
variables are bound the same during the application of the funarg
as at the time it was created, provided that the binding
environment in which the funarg was created still exists on the
stack. Hence if foo is a function that accepts a functional
argument, such as
(defun foo (f)
(append one-value (f the-other-value) ))
then
(foo (*function bar))
works, but
(foo (prog (x y z)
(do something)
(return (*function bar)) ))
does not if bar intends to reference the prog variables x, y,
and z. *function is intended to help solve the "funarg
problem," however it only works in some easy cases. In
Page 18 3. 3.5 11/18/73
The Basic Processes of LISP
***** ROUGH DRAFT #9905 *****
particular, two general cases of the funarg problem are not
solved. funarg's generated by *function are intended for use as
functional arguments, and cannot be returned as values of
functional applications. Also, due to the implementation, which
essentially generates a copy of the environment at the time
*function is applied, assignments to variables in this copied
environment do not affect the values of those variables in the
environment which exists at the time *function is applied. Thus,
the user should be careful in his use of *function to make sure
that his use does not exceed the limitations of the funarg
mechanism.
A funarg has the form
(funarg <function> . <pdl-ptr>)
comment FSUBR
comment ignores its arguments and returns the atomic symbol
comment. Example:
(defun foo (x)
(cond ((null x) 0)
(t (comment x has something in it)
(1+ (foo (cdr x))))))
Usually it is preferable to comment code using the
semicolon-macro feature of the standard input syntax. This
allows the user to add comments to his code which are ignored by
the input package. Example:
(defun foo (x)
(cond ((null x) 0)
(t (1+ (foo (cdr x)))) ;x has something in it
))
prog2 LSUBR 2 or more args
Prog2 evaluates its arguments from left to right, like any
lsubr, and returns the value of its second argument.
Examples:
(prog2 (do-this) (do-that)) ;get 2 things evaluated
(setq x (prog2 nil y
(setq y x))) ;parallel assignment.
;exchanges x and y.
11/18/73 3. 3.5 Page 19
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
progn LSUBR 1 or more args
progn essentially evaluates all of its arguments and returns the
value of the last one. Although lambda-expressions, prog-forms,
do-forms, cond-forms and iog-forms all use progn implicitly,
there are occasions upon which one needs to evaluate a number of
forms for side-effects when not in these forms. progn serves this
purpose. Example:
(progn (setq a 1) (cons a '(stuff))) => (1 stuff)
arg SUBR 1 arg
(arg nil), when evaluated inside a lexpr, gives the number of
arguments supplied to that lexpr.
(arg i), when evaluated inside a lexpr, gives the value of the
i'th argument to the lexpr. i must be a fixnum in this case. It
is an error if i is less than 1 or greater than the number of
arguments supplied to the lexpr. Example:
(defun foo nargs ; define a lexpr foo.
(print (arg nil)) ; print the number of args supplied.
(print (arg 2)) ; print the second argument.
(+ (arg 1) (arg 3))) ; return the sum of 1st and 3rd args.
setarg SUBR 2 args
Setarg is used only inside a lexpr. (setarg i x) sets the
lexpr's i'th argument to x. i must be greater than zero and not
greater than the number of arguments passed to the lexpr. After
(setarg i x) has been done, (arg i) will return x.
listify SUBR 1 arg
listify is a function which efficiently manufactures a list of n
of the arguments of a lexpr. With a positive argument n, it
returns a list of the first n arguments of the lexpr. With a
negative argment n, it returns a list of the last (abs n)
arguments of the lexpr. Basically, it works as if defined as
follows:
(defun listify (n)
(cond ((minusp n)
(*listify (arg nil) (+ (arg nil) n 1)))
(t
(*listify n 1)) ))
Page 20 3. 3.5 11/18/73
The Basic Processes of LISP
***** ROUGH DRAFT #9905 *****
(defun *listify (n m) ; auxiliary function.
(do ((i n (1- i))
(l nil (cons (arg i) l)))
((< i m) l) ))
funcall LSUBR 1 or more args
(funcall f a1 a2 ... an) calls the function f with the arguments
a1, a2, ..., an. It is similar to apply except that the seperate
arguments are given to funcall, rather than a list of arguments.
If f is an expr, a lexpr, a subr, or an lsubr, the arguments are
not re-evaluated. If f is a fexpr or an fsubr there must be
exactly one argument. f may not be a macro.
Example:
(setq cons 'plus)
(cons 1 2) => (1 . 2)
(funcall cons 1 2) => 3
11/18/73 3. 3.5 Page 21
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
This page intentionally left blank.
Page 22 3. 3.5 11/18/73
Functions for Manipulating List Structure
***** ROUGH DRAFT #9905 *****
4. Functions for Manipulating List Structure
4.1 Functions that Examine Existing List Structure
car SUBR 1 arg
Takes the first part of a cons.
Examples:
(car '(a b)) => a
(car '(1 . 2)) => 1
cdr SUBR 1 arg
Takes the second part of a cons.
Example: (cdr '(a b c)) => (b c)
Note: the cdr of an atomic symbol is its property list.
c...r SUBR 1 arg
All the compositions of up to four cars and cdrs are defined as
functions in their own right. The names begin with c and end
with r, and in between is the sequence of a's and d's
corresponding to the composition performed by the function.
For example,
(cddadr x) = (cdr (cdr (car (cdr x))))
Some of the most commonly used ones are: cadr, which gets the
second element of a list. caddr, which gets the third element of
a list. cadddr, which gets the fourth element of a list.
11/18/73 4.1 Page 23
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
assoc SUBR 2 args
(assoc x y) looks up x in the association list (list of dotted
pairs) y. The value is the first dotted pair whose car is equal
to x, or nil if there is none such.
Examples:
(assoc 'r '((a . b) (c . d) (r . x) (s . y) (r . z)))
=> (r . x)
(assoc 'fooo '((foo . bar) (zoo . goo))) => nil
It is okay to rplacd the result of assoc as long as it is not
nil. Example:
(setq values '((x . 100) (y . 200) (z . 50)))
(assoc 'y values) => (y . 200)
(rplacd (assoc 'y values) 201)
(assoc 'y values) => (y . 201) now
(One should always be careful about using rplacd however)
Assoc could have been defined by:
(defun assoc (x y)
(cond ((null y) nil)
((equal x (caar y)) (car y))
((assoc x (cdr y))) ))
assq SUBR 2 args
Assq is like assoc except that the comparison uses eq instead of
equal. Assq could have been defined by:
(defun assq (x y)
(cond ((null y) nil)
((eq x (caar y)) (car y))
((assq x (cdr y))) ))
sassoc SUBR 3 args
(sassoc x y z) is like (assoc x y) except that if x is not found
in y, instead of returning nil sassoc calls the function z with
no arguments. Sassoc could have been defined by:
(defun sassoc (x y z)
(or (assoc x y)
(apply z nil)))
Page 24 4.1 11/18/73
Functions for Manipulating List Structure
***** ROUGH DRAFT #9905 *****
sassq SUBR 3 args
(sassq x y z) is like (assq x y) except that if x is not found in
y, instead of returning nil sassq calls the function z with no
arguments. Sassq could have been defined by:
(defun sassq (x y z)
(or (assq x y)
(apply z nil)))
eq SUBR 2 args
Eq is a predicate. (eq x y) is t if x and y are exactly the same
object, nil otherwise. (cf. equal). It should be noted that
things that print the same are not necessarily eq to each other.
In particular, numbers with the same value need not be eq. In
general, two symbols with the same print-name are eq, but it is
possible with maknam or varible obarrays to generate symbols
which have the same print-name but are not eq.
Examples:
(eq 'a 'b) => nil
(eq 'a 'a) => t
(eq '(a b) '(a b)) => nil (usually)
(setq x '(a b)) (eq x x) => t since it is the same
'(a b) in both arguments.
(eq 1 1) => t or nil depending on the implementation.
equal SUBR 2 args
The equal predicate returns t if its arguments have similar
structure. (cf. eq) Two numbers are equal if they have the same
value (flonums are never equal to fixnums though). Two strings
are equal if they have the same length, and the contents are the
same. All other atomic objects are equal if and only if they are
eq. For dotted pairs and lists, equal is defined recursively as:
(equal x y) = (or (eq x y)
(and (equal (car x) (car y))
(equal (cdr x) (cdr y))))
As a consequence of this definition, it may be seen that equal
need not terminate when applied to looped list structure. In
addition, eq always implies equal. An intuitive definition of
equal (which is not quite correct) is that two objects are equal
if they look the same when printed out.
11/18/73 4.1 Page 25
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
last SUBR 1 arg
Last returns the last dotted pair of the list which is its
argument. Example:
(setq x '(a b c d))
(last x) => (d)
(rplacd (last x) '(e f))
x => (a b c d e f)
Last could have been defined by:
(defun last (x)
(cond ((null x) x)
((null (cdr x)) x)
((last (cdr x))) ))
In some implementations, the null check above may be replaced by
an atom check, which will catch dotted lists. Code which depends
on this fact should not be written though, because all
implementations are subject to change on this point.
length SUBR 1 arg
Length returns the length of its argument, which must be a list.
The length of a list is the number of top-level conses in it.
Examples:
(length nil) => 0
(length '(a b c d)) => 4
(length '(a (b c) d)) => 3
Length could have been defined by:
(defun length (x)
(cond ((null x) 0)
((1+ (length (cdr x)))) ))
The warning about dotted lists given under last applies also to
length.
Page 26 4.1 11/18/73
Functions for Manipulating List Structure
***** ROUGH DRAFT #9905 *****
member SUBR 2 args
(member x y) returns nil if x is not a member of the list y.
Otherwise, it returns the portion of y beginning with the first
occurrence of x. The comparison is made by equal. y is searched
on the top level only. Example:
(member 'x '(1 2 3 4)) => nil
(member 'x '(a (x y) c x d e x f)) => (x d e x f)
Note that the value returned by member is eq to the portion of
the list beginning with x. Thus rplaca on the result of member
may be used, if you first check to make sure member did not
return nil. Member could have been defined by:
(defun member (x y)
(cond ((null y) nil)
((equal x (car y)) y)
((member x (cdr y))) ))
memq SUBR 2 args
Memq is like member, except eq is used for the comparison. Memq
could have been defined by:
(defun memq (x y)
(cond ((null y) nil)
((eq x (car y)) y)
((memq x (cdr y))) ))
not SUBR 1 arg
Not returns t if its argument is nil, otherwise it returns nil.
null SUBR 1 arg
This is the same as not.
sxhash SUBR 1 arg
Sxhash computes a hash code of an S-expression, and returns it as
a fixnum which may be positive or negative. A property of sxhash
is that (equal x y) implies (= (sxhash x) (sxhash y)). The
number returned by sxhash is some possibly large number in the
11/18/73 4.1 Page 27
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
range allowed by fixnums. It is guaranteed that:
1) sxhash for an atomic symbol will always be positive.
2) sxhash of any particular expression will be constant in a
particular implementation for all time.
3) Two different implementations may hash the same expression
into different values.
4) sxhash of any object of type random will be zero.
5) sxhash of a fixnum will = that fixnum.
Page 28 4.1 11/18/73
Functions for Manipulating List Structure
***** ROUGH DRAFT #9905 *****
4.2 Functions that Create New List Structure
cons SUBR 2 args
This is a primitive function to construct a new dotted pair
whose car is the first argument to cons, and whose cdr is the
second argument to cons. Thus the following identities hold:
(eq (car (cons x y)) x) => t
(eq (cdr (cons x y)) y) => t
Examples:
(cons 'a 'b) => (a . b)
(cons 'a (cons 'b (cons 'c nil))) => (a b c)
(cons 'a '(b c d e f)) => (a b c d e f)
ncons SUBR 1 arg
(ncons x) = (cons x nil) = (list x)
xcons SUBR 2 args
xcons ("exchange cons") is like cons except that the order of
arguments is reversed.
Example:
(xcons 'a 'b) => (b . a)
xcons could have been defined by: (defun xcons (x y) (cons y x))
list LSUBR 0 or more args
list constructs and returns a list of the values of its
arguments.
Example:
(list 3 4 'a (car '(b . c)) (+ 6 -2)) => (3 4 a b 4)
11/18/73 4.2 Page 29
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
append LSUBR 0 or more args
The arguments to append are lists. The result is a list which is
the concatenation of the arguments. The arguments are not
changed (cf nconc). For example,
(append '(a b c) '(d e f) nil '(g)) => (a b c d e f g)
A version of append which only accepts two arguments could have
been defined by:
(defun append (x y)
(cond ((null x) y)
((cons (car x) (append (cdr x) y)) )))
The generalization to any number of arguments could then be made
using a lexpr:
(defun full-append argcount
(and (> argcount 0)
(do ((i (1- argcount) (1- i))
(val (arg argcount)))
((< i 1)
val)
(setq val (append (arg i) val)))))
reverse SUBR 1 arg
Given a list as argument, reverse creates a new list whose
elements are the elements of its argument taken in reverse order.
Reverse does not modify its argument, unlike nreverse which is
faster but does modify its argument. Example:
(reverse '(a b c d)) => (d c b a)
Reverse could have been defined by:
(defun reverse (x)
(do ((l x (cdr l)) ; scan down argument,
(r nil
(cons (car l) r))) ; putting each element into list
((null l) r))) ; until no more elements.
Page 30 4.2 11/18/73
Functions for Manipulating List Structure
***** ROUGH DRAFT #9905 *****
subst SUBR 3 args
(subst x y z) substitutes x for all occurrences of y in z, and
returns the modified z. The original z is unchanged, as subst
recursively copies all of z replacing elements eq to y as it
goes. If x and y are nil, z is completely copied, which is a
convenient way to copy arbitrary list structure.
Example:
(subst 'Tempest 'Hurricane
'(Shakespeare wrote (The Hurricane)))
=> (Shakespeare wrote (The Tempest))
Subst could have been defined by:
(defun subst (x y z)
(cond ((equal y z) x) ;if item equals y, replace.
((atom z) z) ;if no substructure, return arg.
((cons (subst x y (car z))
(subst x y (cdr z))))))
sublis SUBR 2 args
sublis makes substitutions for atomic symbols in an S-expression.
The first argument to sublis is a list of dotted pairs. The
second argument is an S-expression. The return value is the
S-expression with atoms that are the car of a dotted pair
replaced by the cdr of that dotted pair. The argument is not
modified - new conses are created where necessary and only where
necessary, so the newly created structure shares as much of its
substructure as possible with the old. For example, if no
successful substitutions are made, the result is eq to sublis's
second argument.
Example:
(sublis '((x . 100) (z . zprime))
'(plus x (minus g z x p) 4))
=> (plus 100 (minus g zprime 100 p) 4)
11/18/73 4.2 Page 31
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
4.3 Functions that Modify Existing List Structure
rplaca SUBR 2 args
(rplaca x y) changes the car of x to y and returns (the modified)
x. Example:
(setq x '(a b c))
(rplaca x 'd) => (d b c)
Now x => (d b c)
rplacd SUBR 2 args
(rplacd x y) changes the cdr of x to y and returns (the modified)
x. Example:
(setq x '(a b c))
(rplacd x 'd) => (a . d)
Now x => (a . d)
nconc LSUBR 0 or more args
nconc takes lists as arguments. It returns a list which is the
arguments concatenated together. The arguments are changed,
rather than copied. (cf. append)
Example:
(nconc '(a b c) '(d e f)) => (a b c d e f)
Note that the constant (a b c) has been changed to (a b c d e f).
If this form is evaluated again, it will yield (a b c d e f d e
f).
nconc could have been defined by:
(defun nconc (x y) ;for simplicity, this definition
(cond ((null x) y) ;only works for 2 arguments.
(t
(rplacd (last x) y);hook y onto x
x))) ;and return the modified x.
nreverse SUBR 1 arg
nreverse reverses its argument, which should be a list. The
argument is destroyed by rplacd's all through the list (cf.
reverse).
Example:
Page 32 4.3 11/18/73
Functions for Manipulating List Structure
***** ROUGH DRAFT #9905 *****
(nreverse '(a b c)) => (c b a)
nreverse could have been defined by:
(defun nreverse (x)
(cond ((null x) nil)
((*nrev x nil))))
(defun *nrev (x y) ;auxiliary function
(cond ((null (cdr x)) (rplacd x y))
((*nrev (cdr x) (rplacd x y)))))
;; this last call depends on order of argument
evaluation.
delete LSUBR 2 or 3 args
(delete x y) returns the list y with all top-level occurrences of
x removed. Equal is used for the comparison. The argument y is
actually modified (rplacd'ed) when instances of x are spliced
out.
(delete x y n) is like (delete x y) except only the first n
instances of x are deleted. n is allowed to be zero. If n is
greater than the number of occurences of x in the list, all
occurrences of x in the list will be deleted.
Example: (delete 'a '(b a c (a b) d a e)) => (b c (a b) d e)
delete could have been defined by:
(defun delete nargs ; lexpr definition for 2 or 3 args
(*delete (arg 1) ; pass along arguments...
(arg 2)
(cond ((= nargs 3) (arg 3))
(123456789)))) ; infinity
(defun *delete (x y n) ;auxiliary function
(cond ((or (null y) (zerop n)) y)
((equal x (car y)) (*delete x
(cdr y)
(1- n)))
((rplacd y (*delete x (cdr y) n)))))
delq LSUBR 2 or 3 args
delq is the same as delete except that eq is used for the
comparison instead of equal. See delete.
11/18/73 4.3 Page 33
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
This page intentionally left blank.
Page 34 4.3 11/18/73
Flow of Control
***** ROUGH DRAFT #9905 *****
5. Flow of Control
MACLISP provides a variety of structures for flow of control.
Conditionals allow control to branch depending on the value of a
predicate. "and" and "or" are basically one-arg conditionals,
while cond is a very generalized multi-armed conditional.
Recursion consists of doing part of the work that is to be
done oneself, and handing off the rest to someone else to take
care of, when that someone else happens to be (another invocation
of) oneself.
Iteration is a control structure present in most languages.
It is similar to recursion but sometimes more useful. MACLISP
contains a generalized iteration facility. The iteration
facility also permits those who like "gotos" to use them.
Nonlocal exits are similar to a return, except that the return
is from several levels of function calling rather than just one,
and is determined at run time. These are mostly used for
applications like escaping from the middle of an algorithm when
it is discovered that the algorithm is not applicable.
Errors are a type of non-local exit used by the lisp
interpreter when it discovers a condition that it does not like.
Errors have the additional feature of correctability, which
allows a user-specified function (most often a break loop), to
get a chance to come in and correct the error or at least inspect
what was happening and determine what caused it, before the
nonlocal exit occurs. This is explained in detail in section
12.4.
5.1 Conditionals
and FSUBR
'and' evaluates its arguments one at a time, from left to right.
If any argument evaluates to nil, 'and' immediately returns nil
without evaluating the remaining arguments. If all the arguments
evaluate non-nil, 'and' returns the value of its last argument.
'and' can be used both for logical operations, where nil stands
for False and t stands for True, and as a conditional expression.
Examples:
(and x y)
11/18/73 5.1 Page 35
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
(and (setq temp (assq x y))
(rplacd temp z))
(and (null (errset (something)))
(princ "There was an error."))
Note: (and) => t, which is the identity for this operation.
or FSUBR
'or' evaluates its arguments one by one from left to right. If
an argument evaluates to nil, 'or' proceeds to evaluate the next
argument. If there are no more arguments, 'or' returns nil. But
if an argument evaluates non-nil, 'or' immediately returns that
value without evaluating any remaining arguments. 'or' can be
used both for logical operations, where nil stands for False and
t for True, and as a conditional expression.
Note: (or) => nil, the identity for this operation.
cond FSUBR
cond processes its arguments, called "clauses," from left to
right. The car of each clause, called the "antecedent," is
evaluated. If it is nil, cond advances to the next clause.
Otherwise, the cdr of the clause is treated as a list of forms,
called "consequents," which are evaluated from left to right.
After evaluating the consequents, cond returns without inspecting
any remaining clauses. The value is the value of the last
consequent evaluated, or the value of the antecedent if there
were no consequents in the clause. If cond runs out of clauses
(i.e. if every antecedent is nil), the value of the cond is nil.
Example:
(cond ((zerop x) (+ x 3)) ;first clause.
;(zerop x) is antecedent.
;(plus x 3) is consequent.
((null y)
(setq x 4)
(cons x z)) ;a clause with 2 consequents
(z) ;a clause with no consequents.
;the antecedent is just z.
) ;this is the end of the cond.
This is like the traditional LISP 1.5 cond except that it is not
necessary to have exactly one consequent in each clause, and it
is permissible to run out of clauses.
Page 36 5.1 11/18/73
Flow of Control
***** ROUGH DRAFT #9905 *****
5.2 Iteration
prog FSUBR
prog is the "program" function. It provides temporary variables
and the ability to do "go-tos." The form of a prog is:
| <tag> |
(prog (<var>...) < > ...)
| <statement> |
The first thing in a prog is a list of temporary variables
<var>. Each variable has its value saved when the prog is
entered and restored when the prog is left. The variables are
initialized to nil when the prog is entered, thus they are said
to be "bound to nil" by the prog.
The rest of a prog is the body. An item in the body may be an
atomic symbol which is a <tag> or a non-atomic <statement>.
prog, after binding the temporary variables, evaluates its
body sequentially. <tag>s are skipped over; <statement>s are
evaluated but the values are ignored. If the end of the body is
reached, prog returns nil. If (return x) is evaluated, prog
stops evaluating its body and returns the value of x. If (go
tag) is seen, prog jumps to the part of the body labelled with
the tag. The argument to 'go' is not evaluated unless it is
non-atomic.
It should be noted that the prog function is an extension of
the LISP 1.5 prog function, in that go's and return's may occur
in more places than LISP 1.5 allowed. However, the LISP
compilers implemented on ITS, Multics, and the DECsystem 10 for
MACLISP require that go's and return's be lexically within the
scope of the prog. This makes a function which does not contain a
prog, but which contains a go or return uncompilable.
See also the 'do' function, which uses a body similar to
prog. The do function and the catch and throw functions are
included in MACLISP as an attempt to encourage goto-less
programming style, which leads to more readable, more easily
maintained code. The programmer is recommended to use these
functions instead of prog wherever possible.
11/18/73 5.2 Page 37
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
Example:
(prog (x y z) ;x, y, z are prog variables - temporaries.
(setq y (car w) z (cdr w)) ;w is a free variable.
loop
(cond ((null y) (return x))
((null z) (go err)))
rejoin
(setq x (cons (cons (car y) (car z))
x))
(setq y (cdr y)
z (cdr z))
(go loop)
err
(break are-you-sure? t)
(setq z y)
(go rejoin))
do FSUBR
do provides a generalized "do loop" facility, with an arbitrary
number of "control variables" whose values are saved when the do
is entered and restored when it is left. It comes in two forms.
The newer form of do is:
(do ((<var> <init> <repeat>)...)
(<end-test> <exit-form>...)
<body>...)
The first argument of do is a list of zero or more control
variable specifiers. Each control variable specifier has as its
car the name of a variable, as its cadr an initial value <init>,
which defaults to nil if it is omitted, and as its caddr a repeat
value <repeat>. If <repeat> is omitted, the <var> is not changed
between loops. All assignment to the control variables is done
in parallel. At the beginning of the first iteration, all the
<init>s are evaluated, then the <var>s are saved, then the <var>s
are setq'ed to the <init>s. Note that the <init>s are evaluated
before the <var>s are bound. At the beginning of each succeeding
iteration those <var>s that have <repeat>s get setq'ed to their
respective <repeat>s. Note that all the <repeat>s are evaluated
before any of the <var>s are changed.
The second argument of do is a list of an end testing predicate
<end-test> and zero or more forms, the <exit-form>s. At the
beginning of each iteration, after processing of the <repeat>s,
the <end-test> is evaluated. If the result is nil, execution
proceeds with the body of the do. If the result is not nil, the
<exit-forms> are evaluated from left to right and then do
returns. The value of the do is the value of the last
Page 38 5.2 11/18/73
Flow of Control
***** ROUGH DRAFT #9905 *****
<exit-form>, or nil if there were no <exit-form>s. Note that the
second argument to do is similar to a cond clause. If the second
argument to do is nil, there is no <end-test> or <exit-form>s,
and the the body of the do is executed only once. In this type
of do it is an error to have <repeat-val>s. This type of do is a
"prog with initial values."
The remaining arguments to do constitute a prog body. When the
end of the body is reached, the next iteration of the do begins.
If return is used, do returns the indicated value and no more
iterations occur.
The older form is:
(do <var> <init-val> <repeat-val> <end-test> <body>...)
The first time through the loop <var> gets the value of
<init-val>; the remaining times through the loop it gets the
value of <repeat-val>, which is re-evaluated each time. Note
that <init-val> is evaluated before the value of <var> is saved.
After <var> is set, <end-test> is evaluated. If it is non-nil,
the do finishes and returns nil. If the <end-test> is nil, the
<body> of the loop is executed. The <body> is like a prog body.
Go may be used. If return is used, its argument is the value of
the do. If the end of the prog body is reached, another loop
begins.
Examples of the old form of do:
(do i 0 (1+ i) (> i (cadr (arraydims x)))
(store (x i) 0)) ;zeroes out the array x
(do zz x (cdr zz) (or (null zz) (zerop (f (car zz)))))
; this applies f to each element of x
; continuously until f returns zero.
Examples of the new form of do:
(do ((x) (y) (z)) (nil) <body>)
is like
(prog (x y z) <body>)
except that when it runs off the end of the <body>, do loops but
prog returns nil.
(do ((x y (f x))) ((p x)) <body>)
is like
(do x y (f x) (p x) <body>)
(do ((x x (cdr x))
(y y (cdr y))
(z nil (cons (f x y) z))) ; exploits parallel assignment
((or (null x) (null y))
11/18/73 5.2 Page 39
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
(nreverse z))) ; typical use of nreverse
; body has been omitted
is like (maplist 'f x y).
(do ((x e (cdr x)) (oldx x x)) ((null x)) <body>)
This exploits the parallel assignment to control variables. On
the first iteration, the value of oldx is whatever value x had
before the do was entered. On succeeding iterations, oldx
contains the value that x had on the previous iteration.
In either form of do, the <body> may contain no forms at all.
go FSUBR
The go function is used to do a "go-to" within the body of a do
or a prog. If the argument is an atom, it is not evaluated.
Otherwise it is repeatedly evaluated until it is an atom. Then
'go' transfers control to the point in the prog labelled by a tag
eq to the argument. If there is no such tag in the prog, it is
an unseen-go-tag error. Example:
(prog (x y z)
(setq x something)
loop
<do something>
(and <some predicate> (go loop)) ;regular go
<do something more>
(go (cond ((minusp x) 'loop) ;"computed go"
(t 'endtag)))
endtag
(return z))
return SUBR 1 arg
return is used to return from a prog or a do. The value of
return's argument is returned by prog or do as its value. In
addition, break recognizes the top level form (return <value>)
specially. If this form is entered at top level in a break,
<value> will be returned as the value of break. If not at
top-level in a break, and not in a prog or do, return will cause
a fail-act error if invoked.
Example:
(prog (x)
(setq x (reverse y))
(or (cddr x) (return (cadr x)))
(return (caddr x)))
Page 40 5.2 11/18/73
Flow of Control
***** ROUGH DRAFT #9905 *****
If y is '(z y x w y u t s), this returns u. If y is '(a b), this
returns a.
11/18/73 5.2 Page 41
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
5.3 Nonlocal Exits
catch FSUBR
Catch is the LISP function for doing structured non-local exits.
(catch x) evaluates x and returns its value, except that if
during the evaluation of x (throw y) should be evaluated, catch
immediately returns y without further evaluating x.
Catch may also be used with a second argument, not evaluated,
which is used as a tag. (catch x b) will catch a (throw y b) but
not a (throw y z). Throw with only one argument always throws to
the nearest catch. Catch with only one argument catches any
throw. It is an error if throw is done when there is no suitable
catch. Example:
(catch
(mapcar (function (lambda (x)
(cond ((minusp x) (throw x negative))
(t (f x)) )))
y)
negative)
which returns a list of f of each element of y if y is all
positive, otherwise the first negative member of y.
The user of catch and throw is recommended to stick to the 2
argument version, which is no less efficient, and tends to reduce
the likelihood of bugs. The one argument versions exist
primarily as an easy way to fix old LISP programs which use
errset and err for non-local exits. This latter practice is
rather confusing, because err and errset are supposed to be used
for error handling, not general program control.
throw FSUBR
Throw is used with catch as a structured nonlocal exit mechanism.
(throw x) evaluates x and throws the value back to the most
recent catch.
(throw x <tag>) throws the value of x back to the most recent
catch labelled with <tag> or unlabelled. Catches with tags not
eq to <tag> are skipped over. x is evaluated but <tag> is not.
See the description of catch for further details.
Page 42 5.3 11/18/73
Flow of Control
***** ROUGH DRAFT #9905 *****
5.4 Causing and Controlling Errors
err FSUBR
(err) causes an error which is handled the same as a LISP error
except that there is no preliminary user interrupt.
(err x) is like (err) except that if control returns to an
errset, the value of the errset will be the result of evaluating
x, instead of nil.
(err x nil) is the same as (err x). (err x y), where y is not
nil, is like (err x) except that x is not evaluated until just
before the errset returns it. That is, x is evaluated after
unwinding the pdl and restoring the bindings. y is not
evaluated.
Note: some people use err and errset where catch and throw are
indicated. This is a very poor programming practice. See
writeups of catch and throw for details.
error LSUBR 0 to 3 args
This is a function which allows user functions to signal their
own errors using the LISP error system.
(error) is the same as (err).
(error <message>) signals a simple error - no datum is printed
and no user interrupt is signalled. The error message typed out
is <message>.
(error <message> <datum>) signals an error with <message> as the
message to be typed out, <datum> as the LISP object to be printed
in the error message. No user interrupt is signalled.
(error <message> <datum> <uint-chn>) signals an error but first
signals a user interrupt on channel <uint-chn>, provided that
there is such a channel and it has a non-nil service function.
<uint-chn> may be the channel number or the atomic symbol whose
value is the interrupt service function for the channel -- see
section 11.4.2. If the service function returns an atom, error
goes ahead and signals a regular error. If the service function
returns a list, error returns as its value the car of that list.
In this case it was a "correctable" error.
11/18/73 5.4 Page 43
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
errset FSUBR
Errset evaluates its first argument. If no errors occur, the
result is consed with nil and returned. If an error occurs
during the evaluation of the first argument, the error is
prevented from escaping from inside the errset and errset returns
nil. Errset may also be made to return any arbitrary value by
use of the err function.
If a second argument is given to errset, it is not evaluated. If
it is nil, no error message will be printed if an error occurs
during the evaluation of errset's first argument. If the second
argument is not nil, or if errset is used with only one argument,
any error messages generated will be printed.
Examples:
If you are not sure x is a number:
(errset (setq x (add1 x)))
This last example may not work in compiled code if the compiler
chooses to open-code the add1 rather than calling the add1
subroutine. The user of such code must be extremely careful if
he wishes to use it compiled.
To suppress message if the value of a is not an atomic symbol:
(errset (set a b) nil)
To do the same but generate one's own message:
(or (errset (set a b) nil)
(print (list a 'is 'not 'a 'variable)))
Page 44 5.4 11/18/73
Manipulating the Constituents of Atomic Symbols
***** ROUGH DRAFT #9905 *****
6. Manipulating the Constituents of Atomic Symbols
6.1 The Value Cell
Each atomic symbol has associated with it a "value cell," which is
a piece of storage that can hold a LISP object. Initially this value
cell is "unbound" or "undefined," i.e. empty. An object can be placed
into an atomic symbol's value cell by setq'ing or binding. Once this
has been done, this object will be returned when the atomic symbol is
evaluated. The atomic symbol is said to have a value of the object.
setq FSUBR
setq is used to assign values to variables (atomic symbols.)
setq takes its arguments in pairs, and processes them
sequentially, left to right. The first member of each pair is
the variable, the second is the value. The value is evaluated
but the variable is not. The value of the variable is set to the
value specified. You must not setq the special atomic-symbol
constants t and nil. The value returned by setq is the last
value assigned, i.e. the value of its last argument.
Example: (setq x (+ 1 2 3) y (cons x nil))
returns (6) and gives x a value of 6 and y a value of (6).
Note that the first assignment is processed before the second
assignment is done, resulting in the second use of x getting the
value assigned in the first pair of the setq.
set SUBR 2 args
Set is like setq except that the first argument is evaluated;
also set only takes one pair of arguments. The first argument
must evaluate to an atomic symbol, whose value is changed to the
value of the second argument. Set returns the value of its
second argument. Example:
(set (cond ((predicate) 'atom1) (t 'atom2))
'stba)
11/18/73 6.1 Page 45
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
evaluates to stba and gives either atom1 or atom2 a value of
stba.
Set could have been defined by:
(defun set (x y)
(apply 'setq (list x (list 'quote y)) ))
boundp SUBR 1 arg
The argument to boundp must be an atomic symbol. If it has a
value, cons of nil with that value is returned. Otherwise nil is
returned. Example:
(boundp 't) => (nil . t) ;since the value of t is t
definedp SUBR 1 arg
This predicate returns t if its argument (a symbol) has a value,
and nil otherwise.
makunbound SUBR 1 arg
The argument to makunbound must be an atomic symbol. Its value
is removed and it becomes undefined, which is the initial state
for atomic symbols.
Example:
(setq a 1)
a => 1
(makunbound 'a)
a => unbnd-vrbl error.
Makunbound returns its argument.
Page 46 6.1 11/18/73
Manipulating the Constituents of Atomic Symbols
***** ROUGH DRAFT #9905 *****
6.2 The Property List
A property-list is a list with an even number of elements. Each
pair of elements constitutes a property: the first element is called
the "indicator" and the second is called the "value." The indicator
is generally an atomic symbol which serves as the name of the
property. For example, one type of functional property uses the atom
expr as its indicator. The value is a LISP object. In the case of an
expr-property, the value is a list beginning with lambda. An example
of a property list with two properties on it is:
(expr (lambda (x) (plus 14 x)) foobar t)
The first property has indicator expr and value (lambda (x) (plus 14
x)), the second property has indicator foobar and value t.
Each atomic symbol has associated with it a property-list which is
kept on its cdr. It is also possible to have "disembodied" property
lists which are not associated with any atom. These also keep the
property list on their cdr, as the form of a disembodied property list
is (<anything> . plist). The way to create a disembodied property
list is (ncons nil).
The user familiar with LISP 1.5 will want to note that the property
list "flags" which are allowed on LISP 1.5 property lists do not exist
in MACLISP.
get SUBR 2 args
(get x y) gets x's y-property. x can be an atomic symbol or a
disembodied property list. The value of x's y property is
returned, unless x has no y-property in which case nil is
returned. Example:
(get 'foo 'bar)
nil ;foo has no bar property
(putprop 'foo 'zoo 'bar) ;give foo a bar property
zoo
(get 'foo 'bar)
zoo
(cdr 'foo) ;look at foo's property list.
(bar zoo ...other properties...)
11/18/73 6.2 Page 47
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
getl SUBR 2 args
(getl x y) is like get except that y is a list of properties
rather than just a single property. Getl searches x's property
list until a property in the list y is found. The portion of x's
property list beginning with this property is returned. The car
of this is the property name and the cadr is what get would have
returned. Getl returns nil if none of the properties in y appear
on the property list of x. Getl could have been defined by:
(defun getl (x pl)
(do ((q (cdr x) (cddr q))) ; scan down cdr of x
((or (null q) (memq (car q) pl)) q)))
putprop SUBR 3 args
(putprop x y z) gives x a z-property of y and returns y. x
may an atomic symbol or a disembodied property list. This is
like defprop except that the arguments are evaluated. After
somebody does (putprop x y z), (get x z) will return y.
Example: (putprop 'foo 'bar 'often-with)
defprop FSUBR
(defprop x y z) gives x a z-property of y. The arguments are not
evaluated. Example:
(defprop foo bar often-with)
remprop SUBR 2 args
(remprop x y) removes x's y-property, by splicing it out of x's
property list. The value is t if x had a y-property, nil if it
didn't. x may be an atomic symbol or a disembodied property
list. Example:
(remprop 'foo 'expr) undefines the function foo if it was
defined
by (defun foo (x) ... )
Page 48 6.2 11/18/73
Manipulating the Constituents of Atomic Symbols
***** ROUGH DRAFT #9905 *****
6.3 The Print-Name
Each atomic symbol has an associated character string called its
"print-name," or "pname" for short. This character string is used as
the external representation of the symbol. If the string is typed in,
it is read as a reference to the symbol. If the symbol is asked to be
"print"ed, the string is typed out. Generally pnames are unique -
there is only one atomic symbol whose pname is a particular string of
characters. However, by using multiple obarrays (see section 12.4) or
"uninterned" atomic symbols (ones whose pnames are not "interned" or
registered in an obarray), it is possible to get two atoms with the
same pname.
samepnamep SUBR 2 args
The arguments to samepnamep must evaluate to atomic symbols or to
character strings. The result is t if they have the same pname,
nil otherwise. The pname of a character string is considered to
be the string itself.
Examples:
(samepnamep 'xyz (maknam '(x y z))) => t
(samepnamep 'xyz (maknam '(w x y))) => nil
(samepnamep 'x "x") => t
alphalessp SUBR 2 args
(alphalessp x y), where x and y evaluate to atomic symbols or
character strings, returns t if the pname of x occurs earlier in
alphabetical order than the pname of y. The pname of a
character string is considered to be the string itself.
Examples:
(alphalessp 'x 'x1) => t
(alphalessp 'z 'q) => nil
(alphalessp "x" 'y) => t
11/18/73 6.3 Page 49
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
6.4 Miscellaneous Functions
getchar SUBR 2 args
(getchar x n), where x is an atomic symbol and n is a number,
returns the nth character of x's pname, where n = 1 selects the
first character. The character is returned as a character
object. nil is returned if n is out of bounds.
intern SUBR 1 arg
(intern x), where x is an atomic symbol, puts x on the current
obarray and returns x. Note that it puts x itself on the obarray
and not a copy, thus if there is already an atomic symbol on that
obarray with the same pname, it will automatically get remobed.
remob SUBR The argument to remob must be an atomic symbol. It is
removed from the current obarray if it is interned on that
obarray. This makes the atomic symbol inaccessible to any
S-expressions that may be read in or loaded in the future. remob
returns nil.
maknam SUBR 1 arg
Maknam takes as its argument a list of characters, like readlist,
and returns an uninterned atom whose pname is determined by the
list of characters. Example:
(maknam '(a b 60 d)) => ab0d
gensym LSUBR 0 or more args
gensym creates and returns a new atomic symbol, which is not
interned on the obarray (is not recognized by read.) The atomic
symbol's pname is of the form <prefix><number>, e.g. g0001. The
<number> is incremented each time.
If gensym is given arguments, a numeric argument is used to set
the <number>. The pname of an atomic-symbol argument is used to
set the <prefix>. E.g. (gensym 'foo 40) => f0032
Note that the <number> is in decimal and always four digits, and
Page 50 6.4 11/18/73
Manipulating the Constituents of Atomic Symbols
***** ROUGH DRAFT #9905 *****
the <prefix> is always one character.
11/18/73 6.4 Page 51
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
6.5 Use of Atomic Symbols as Functions
Atomic symbols may be used as names for functions. This is done by
putting the actual function (a subr-object or a lambda-expression) on
the property list of the atomic symbol as a "functional property,"
i.e. under one of the indicators expr, fexpr, macro, subr, lsubr, or
fsubr.
Array properties (see chapter 9) are also considered to be
functional properties, so an atomic symbol which is the name of an
array is also the name of a function.
When an atomic symbol which is the name of a function appears in
function position in a list being evaluated, or is "applied," the
function which it names is used.
args LSUBR 1 or 2 args
(args 'f) determines the number of arguments expected by f. If f
wants n arguments, args returns (nil . n). If f can take from m
to n arguments, args returns (m . n). If f is an fsubr or a
lexpr, expr, or fexpr, the results are meaningless.
(args 'f x), where x is (nil . n) or (m . n), sets the number of
arguments desired by f. This only works for compiled, non-system
functions.
defun FSUBR
defun is used for defining functions. The general form is:
(defun <name> <optional-type>
( <lambda-variable>...)
<body>...)
however, <name> and <type> may be interchanged. <type> may be
expr, fexpr, or macro. If it is omitted, expr is assumed.
Examples:
(defun addone (x) (1+ x)) ;defines an expr
(defun quot fexpr (x) (car x)) ;defines a fexpr
(defun fexpr quot (x) (car x)) ;is the same
(defun zzz expr x
(foo (arg 1)(arg 2))) ;this is how you define a lexpr.
Page 52 6.5 11/18/73
Manipulating the Constituents of Atomic Symbols
***** ROUGH DRAFT #9905 *****
Note: the functions defprop and putprop may also be used for
defining functions.
11/18/73 6.5 Page 53
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
This page intentionally left blank.
Page 54 6.5 11/18/73
Functions on Numbers
***** ROUGH DRAFT #9905 *****
7. Functions on Numbers
For a description of the various types of numbers used in
MACLISP, see chapter 2.
7.1 Arithmetic Functions
7.1.1 Arithmetic Predicates
bigp SUBR 1 arg
The predicate bigp returns its argument if that argument is a
bignum, and nil otherwise.
smallnump SUBR 1 arg
The smallnump predicate returns its argument if it is a fixnum
(as opposed to a bignum or a flonum), nil otherwise.
zerop SUBR 1 arg
The zerop predicate returns t if its argument is fixnum zero or
flonum zero. (There is no bignum zero.) Otherwise it returns
nil.
plusp SUBR 1 arg
The plusp predicate returns t if its argument is strictly greater
than zero, nil if it is zero or negative. It is an error if
the argument is not a number.
11/18/73 7.1.1 Page 55
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
minusp SUBR 1 arg
The minusp predicate returns t if its argument is a negative
number, nil if it is a non-negative number. It is an error if
the argument is not a number.
oddp SUBR 1 arg
The oddp predicate returns t if its argument is an odd number,
otherwise nil. The argument must be a fixnum or a bignum.
signp FSUBR
The signp predicate is used to test the sign of a number. (signp
c x) returns t if x's sign satisfies the test c, nil if it does
not. x is evaluated but c is not. It is an error if x is not a
number. c can be one of the following:
l means x<0
le " x<0
e " x=0
n " x/=0
ge " x>0
g " x>0
Examples:
(signp le -1) => t
(signp n 0) => nil
haulong SUBR 1 arg
(haulong x) returns the number of significant bits in x. x can
be a fixnum or a bignum. The result is the least integer not
less than the base-2 logarithm of |x|+1. Examples:
(haulong 0) => 0
(haulong 3) => 2
(haulong -7) => 3
(haulong 12345671234567) => 40.
Page 56 7.1.1 11/18/73
Functions on Numbers
***** ROUGH DRAFT #9905 *****
7.1.2 Comparison
= SUBR 2 args
(= x y) is t if x and y are numerically equal. x and y must be
both fixnums or both flonums.
greaterp LSUBR 2 or more args
Greaterp compares its arguments, which must be numbers, from left
to right. If any argument is not greater than the next, greaterp
returns nil. But if the arguments to greaterp are strictly
decreasing, the result is t. Example:
(greaterp 4 3) => t
(greaterp 1 1) => nil
(greaterp 4.0 3.6 -2) => t
(greaterp 4 3 1 2 0) => nil
> SUBR 2 args
(> x y) is t if x is strictly greater than y, and nil otherwise.
x and y must be both fixnums or both flonums.
lessp LSUBR 2 or more args
Lessp compares its arguments, which must be numbers, from left to
right. If any argument is not less than the next, lessp returns
nil. But if the arguments to lessp are strictly increasing, the
result is t. Example:
(lessp 3 4) => t
(lessp 1 1) => nil
(lessp -2 3.6 4) => t
(lessp 0 2 1 3 4) => nil
11/18/73 7.1.2 Page 57
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
< SUBR 2 args
(< x y) is t if x is strictly less than y, and nil otherwise. x
and y must be both fixnums or both flonums.
max LSUBR 1 or more args
Max returns the largest of its arguments, which must be numbers.
min LSUBR 1 or more args
Min returns the smallest of its arguments, which must be numbers.
Page 58 7.1.2 11/18/73
Functions on Numbers
***** ROUGH DRAFT #9905 *****
7.1.3 Conversion
fix SUBR 1 arg
(fix x) converts x to a fixnum or a bignum depending on its
magnitude. Examples:
(fix 7.3) => 7
(fix -1.2) => -2
float SUBR 1 arg
(float x) converts x to a flonum. Example:
(float 4) => 4.0
abs SUBR 1 arg
(abs x) => |x|, the absolute value of the number x. Abs could
have been defined by:
(defun abs (x) (cond ((minusp x) (minus x))
(x) ))
minus SUBR 1 arg
Minus returns the negative of its argument, which can be any kind
of number. Examples:
(minus 1) => -1
(minus -3.6) => 3.6
haipart SUBR 2 args
(haipart x n) extracts n leading or trailing bits from the
internal representation of x. x may be a fixnum or a bignum. n
must be a fixnum. The value is returned as a fixnum or a bignum.
If n is positive, the result contains the n high-order bits of
abs(x). If n is negative, the result contains the abs(n)
low-order bits of abs(x). If abs(n) is bigger than the number of
significant bits in x, abs(x) is returned.
11/18/73 7.1.3 Page 59
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
Examples:
(haipart 34567 7) => 162
(haipart 34567 -5) => 27
(haipart -34567 -5) => 27
Page 60 7.1.3 11/18/73
Functions on Numbers
***** ROUGH DRAFT #9905 *****
7.1.4 Addition
plus LSUBR 0 or more args
Plus returns the sum of its arguments, which may be any kind of
numbers.
+ LSUBR 0 or more args
+ returns the sum of its arguments. The arguments must be
fixnums, and the result is always a fixnum. Overflow is ignored.
Examples:
(+ 2 6 -1) => 7
(+ 3) => 3 ;trivial case
(+) => 0 ;identity element
+$ LSUBR 0 or more args
+$ returns the sum of its arguments. The arguments must be
flonums and the result is always a flonum. Examples:
(+$ 4.1 3.14) => 7.24
(+$ 2.0 1.5 -3.6) => -0.1
(+$ 2.6) => 2.6 ;trivial case
(+$) => 0.0 ;identity element
add1 SUBR 1 arg
(add1 x) => x + 1. x may be any kind of number.
1+ SUBR 1 arg
(1+ x) => x+1. x must be a fixnum. The result is always a
fixnum. Overflow is ignored.
1+$ SUBR 1 arg
(1+$ x) => x+1.0. x must be a flonum. The result is always a
flonum.
11/18/73 7.1.4 Page 61
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
7.1.5 Subtraction
difference LSUBR 1 or more args
difference returns its first argument minus the rest of its
arguments. It works for any kind of numbers.
- LSUBR 0 or more args
This is the fixnum-only subtraction function. It does not detect
overflows.
(-) => 0, the identity element
(- x) => the negative of x.
(- x y) => x - y.
(- x y z) => x - y - z
etc.
-$ LSUBR 0 or more args
This is the flonum-only subtraction function.
(-$) => 0.0, the identity element
(-$ x) => the negation of x.
(-$ x y) => x - y.
(-$ x y z) => x - y - z.
etc.
*dif SUBR 2 args
This is an obsolete arithmetic difference function.
(*dif x y) => x - y.
sub1 SUBR 1 arg
(sub1 x) => x-1. X may be any kind of number.
1- SUBR 1 arg
(1- x) => x-1. x must be a fixnum. The result is always a
fixnum and overflow is not detected.
Page 62 7.1.5 11/18/73
Functions on Numbers
***** ROUGH DRAFT #9905 *****
1-$ SUBR 1 arg
(1-$ x) => x-1.0. x must be a flonum.
11/18/73 7.1.5 Page 63
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
7.1.6 Multiplication
times LSUBR 0 or more args
Times returns the product of its arguments. It works for any
kind of numbers.
* LSUBR 0 or more args
* returns the product of its arguments. The arguments must be
fixnums. Th result is always a fixnum. Overflow is not
detected. Examples:
(* 4 5 -6) => -120.
(* 3) => 3 ;trivial case
(*) => 1 ;identity element
*$ LSUBR 0 or more args
*$ returns the product of its arguments. The arguments must be
flonums and the result is always a flonum. Examples:
(*$ 3.0 2.0 4.0) => 24.0
(*$ 6.1) => 6.1 ;trivial case
(*$) => 1.0 ;identity element
Page 64 7.1.6 11/18/73
Functions on Numbers
***** ROUGH DRAFT #9905 *****
7.1.7 Division
quotient LSUBR 1 or more args
Quotient returns its first argument divided by the rest of its
arguments. The arguments may any kind of number. (cf. / and
/$) Examples:
(quotient 3 2) => 1 ;fixnum division truncates
(quotient 3 2.0) => 1.5 ;but flonum division does not..
(quotient 6.0 1.5 2.0) => 2.0
*quo SUBR 2 args
This is an obsolete arithmetic quotient function.
(*quo x y) => x / y.
/ LSUBR 0 or more args
This is the fixnum-only division function. The arguments must be
fixnums and the result of the division is truncated to an
integer and returned as a fixnum. Note that the name of this
function must be typed in as //, since LISP uses / as an
escape character.
(//) => 1, the identity element.
(// x) => the fixnum reciprocal of x, which
is 0 if |x| > 1.
(// x y) => x/y.
(// x y z) => (x/y)/z.
etc.
/$ LSUBR 0 or more args
This is the flonum-only division function. Note that the name
of this function must be typed in as //$, since LISP uses / as
an escape character.
(//$) => 1.0, the identity element
(//$ x) => the reciprocal of x.
(//$ x y) => x/y
(//$ x y z) => (x/y)/z.
etc.
11/18/73 7.1.7 Page 65
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
remainder SUBR 2 args
(remainder x y) => the remainder of the division of x by y. The
sign of the remainder is the same as the sign of the dividend.
The arguments must be fixnums or bignums.
\ SUBR 2 args
(\ x y) returns the remainder of x divided by y, with the sign of
x. x and y must be fixnums. Examples:
(\ 5 2) => 1
(\ 65. -9.) => 2
(\ -65. 9.) => -2
gcd SUBR 2 args
(gcd x y) => the greatest common divisor of x and y. The
arguments must be fixnums or bignums.
Page 66 7.1.7 11/18/73
Functions on Numbers
***** ROUGH DRAFT #9905 *****
7.1.8 Exponentiation and Log Functions
expt SUBR 2 args
y
(expt x y) = x
The exponent y may be a bignum if the base x is 0, 1, or -1;
otherwise y must be a fixnum. x may be any kind of number.
sqrt SUBR 1 arg
(sqrt x) => a flonum which is the square root of the number x.
isqrt SUBR 1 arg
(isqrt x) => a fixnum which is the square root of x, truncated to
an integer.
exp SUBR 1 arg
x
(exp x) = e
log SUBR 1 arg
(log x) = ln x, the natural log of x.
11/18/73 7.1.8 Page 67
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
7.1.9 Trigonometric Functions
sin SUBR 1 arg
(sin x) gives the trigonometric sine of x. x is in radians. x
may be a fixnum or a flonum.
cos SUBR 1 arg
(cos x) returns the cosine of x. x is in radians. x may be a
fixnum or a flonum.
atan LSUBR 1 or 2 args
(atan x) returns the arctangent of x, in radians. x and y may be
fixnums or flonums. (atan x y) returns the arctangent of x/y, in
radians. y may be 0 as long as x is not also 0.
Page 68 7.1.9 11/18/73
Functions on Numbers
***** ROUGH DRAFT #9905 *****
7.1.10 Random Functions
random LSUBR 0 or 1 arg
(random) returns a random fixnum.
(random nil) restarts the random sequence at its beginning.
(random x), where x is a fixnum, returns a random fixnum between
0 and x-1 inclusive.
11/18/73 7.1.10 Page 69
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
7.2 Logical Operations on Numbers
boole LSUBR 3 or more args
(boole k x y) produces a bitwise Boolean function of x and y
under the control of k. k must be a fixnum between 0 and 17. If
the binary representation of k is abcd, then the truth table for
the Boolean operation is:
y
|01
0| a c
x |
1| b d
If boole has more than three arguments, it goes from left to
right; thus
(boole k x y z) = (boole k (boole k x y) z)
The most common values for k are 1 (and), 7 (or), 6 (xor). You
can get the complement, or logical negation, of x by (boole 6 x
-1).
lsh SUBR 2 args
(lsh x y), where x and y are fixnums, returns x shifted left y
bits if y is positive, or x shifted right |y| bits if y is
negative. 0 bits are shifted in to fill unused positions. The
result is undefined if |y| > 36. Examples:
(lsh 4 1) => 10 (octal)
(lsh 14 -2) => 3
(lsh -1 1) => -2
rot SUBR 2 args
(rot x y) returns as a fixnum the 36-bit representation of x,
rotated left y bits if y is positive, or rotated right |y| bits
if y is negative. X and y must be fixnums. The results are
undefined if |y| > 36. Examples:
(rot 1 2) => 4
(rot -1 7) => -1
(rot 601234 36.) => 601234
(rot 1 -2) => 200000000000 (octal)
Page 70 7.2 11/18/73
Character Manipulation
***** ROUGH DRAFT #9905 *****
8. Character Manipulation
8.1 Character Objects
An atomic symbol with less than two characters in its pname is
often called a "character object" and used to represent an ascii
character. The atomic symbol with a zero-length pname represents
the ascii null character, and the symbols with 1-character pnames
represent the character which is their pname. Functions which
take character objects as input usually also accept a string one
character long or a fixnum equal to the ascii-code value for the
character. Character objects are always interned on the obarray
(see section 6.3).
ascii SUBR 1 arg
(ascii x), where x is a number, returns the character object for
the ascii code x.
Examples:
(ascii 101) => A
(ascii 56) => /.
explode SUBR 1 arg
(explode x) returns a list of characters, which are the
characters that would have been typed out if (prin1 x) was done,
including slashes for special characters but not including extra
newlines inserted to prevent characters from running off the
right margin. Each character is represented by a character
object.
Example:
(explode '(+ 1x 3)) => ( /( + / // /1 x / /3 /) )
;;Note the presence of slashified spaces in this list.
11/18/73 8.1 Page 71
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
explodec SUBR 1 arg
(explodec x) returns a list of characters which are the
characters that would have been typed out if (princ x) was done,
not including extra newlines inserted to prevent characters from
running off the right margin. Special characters are not
slashified. Each character is represented by a character object.
Example:
(explodec '(+ 1x 3)) => ( /( + / /1 x / /3 /) )
exploden SUBR 1 arg
(exploden x) returns a list of characters which are the
characters that would have been typed out if (princ x) was done,
not including extra newlines inserted to prevent lines characters
from running off the right margin. Special characters are not
slashified. Each character is represented by a number which is
the ascii code for that character. cf. explodec. Example:
(exploden '(+ 1x 3)) => (50 53 40 61 170 40 63 51)
flatc SUBR 1 arg
Flatc returns the length of its argument in characters, if it was
printed out without slashifying special characters. (flatc x) is
the same as (length (explodec x)).
flatsize SUBR 1 arg
Flatsize returns the length of its argument in characters, if it
was printed out with special characters slashified. (flatsize x)
is the same as (length (explode x)).
readlist SUBR 1 arg
The argument to readlist is a list of characters. The characters
may be represented either as numbers (ascii codes) or as
character objects. The characters in the list are assembled into
an S-expression as if they had been typed into read (See chapter
12 for a description of read.) If macro characters are used, any
calls to read, readch, tyi, or tyipeek in the macro character
functions take their input from readlists's argument rather than
from an I/O device or a file.
Examples:
(readlist '(a b c)) => abc
Page 72 8.1 11/18/73
Character Manipulation
***** ROUGH DRAFT #9905 *****
(readlist '( /( p r 151 n t / /' f o o /) ))
=> (print (quote foo))
;;Note the use of the slashified special characters left paren,
space, quote, right paren in the argument to readlist.
11/18/73 8.1 Page 73
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
8.2 Functions on Strings
These character string functions only exist at present in the
Multics implementation of MACLISP. They all accept atomic symbols in
place of strings as arguments; in this case the pname of the atomic
symbol is used as the string. When the value of one of these
functions is described as a string, it is always a string and never an
atomic symbol.
getpname SUBR 1 arg
(getpname x) returns the pname of x as a character string. x
must be an atomic symbol.
makeatom SUBR 1 arg
Makeatom returns an atomic symbol, uninterned, whose pname is
given as a character string argument. Example:
(makeatom "foo") => foo ;which is not eq to a
;foo that is read in.
CtoI SUBR 1 arg
CtoI returns as a fixnum the ascii code for the first character
of its argument, which must be a string.
Example: (CtoI "z") => 172
ItoC SUBR 1 arg
ItoC returns a string one character long, consisting of the
character whose ascii code is the argument.
Example: (ItoC 101) => A
catenate LSUBR 0 or more args
The arguments to catenate must be strings. The result is a
string which is all the arguments concatenated together.
Example:
Page 74 8.2 11/18/73
Character Manipulation
***** ROUGH DRAFT #9905 *****
(catenate "abc" "-" "bar") => "abc-bar"
index SUBR 2 args
Index is the PL/I builtin function index. The arguments are
character strings. The position of the first occurrence of the
second argument in the first is returned, or 0 if there is none.
Examples:
(index "foobar" "ba") => 4
(index "foobar" "baz") => 0
(index "goobababa" "bab") => 4
stringlength SUBR 1 arg
The argument to stringlength must be a character string. The
number of characters in it is returned. Examples:
(stringlength "foo") => 3
(stringlength "") => 0
substr LSUBR 2 or 3 args
This is the PL/I substr builtin. (substr x m n) returns a string
n characters long, which is a portion of the string x beginning
with its m'th character and proceeding for n characters. m and n
must be fixnums, x must be a string.
(substr x m) returns the portion of the string x beginning with
its m'th character and continuing until the end of the string.
Examples:
(substr "foobar" 3 2) => "ob"
(substr "resultmunger" 6) => "tmunger"
11/18/73 8.2 Page 75
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
This page intentionally left blank.
Page 76 8.2 11/18/73
Functions Concerning Arrays
***** ROUGH DRAFT #9905 *****
9. Functions Concerning Arrays
LISP provides arrays of any number of dimensions. The contents of
the arrays can be any LISP objects. The different elements of an
array need not be of the same type.
An array is implemented as a space in which to keep the contents of
the array and a function to access it. The name of the function is
the name of the array. The arguments to the function are the
subscripts. LISP arrays are always 0-origin indexed, that is, the
subscript values start at 0. The subscripts must be fixnums. The
array-accessing function returns as its value the contents of the
selected array cell and as a side-effect saves a pointer to this cell
for the use of the store function (see below). The functional
property of an array is kept under the indicator array.
There is a special type of array called an "un garbage collected"
array. If an object other than an atomic symbol is only referenced
from an element of a normal array, that object will stay around, but
if an object is only referenced by an element of an ungarbage
collected array then the object will be taken away by the garbage
collector and the element of the ungarbage- collected array will be
changed to something random. In other words, ungarbage collected
arrays do not protect the objects they contain.
Some implementations of MACLISP also have number arrays, which can
only hold either fixnums or flonums (bot not both), but which are more
efficient for this purpose than regular arrays. These are not
described here.
Here is an example of a use of arrays:
(array x t 500.)
(array y t 500.) ;define 2 arrays
(do i 0 (1+ i) (= i (cadr (arraydims 'x)))
(store (x i) (//$ (float i) 100.0)) ;x(i):=...
(store (y i) (sin (x i))) ;y(i):=...
) ;end loop
(plot 'x 'y) ;call some random plotting routine
11/18/73 9. Page 77
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
*array LSUBR 3 or more args
(*array x y b1 b2 ... bn) defines x to be an n-dimensional array.
The first subscript may range from 0 to b1-1, the second from 0
to b2-1, etc. If y is t a normal array is created; if y is nil
an "ungarbage-collected" array is created.
array FSUBR
(array x y b1 b2 ... bn) is like (*array x y b1 b2 ... bn) except
that x is not evaluated. The other arguments are evaluated.
*rearray LSUBR 1 or more args
*rearray is used to redefine the dimensions of an array.
(*rearray x) gets rid of the array x. x is evaluated - it must
evaluate to an atomic symbol. The value is t if it was an array,
nil if it was not.
(*rearray x type dim1 dim2 ... dimn) is like (*array x type dim1
dim2 ... dimn) except that the contents of the previously
existing array named x are copied into the new array named x.
store FSUBR
The first argument to store must be a subscripted reference to an
array. The second argument is evaluated and stored into the
referenced cell of the array. Store evaluates its second
argument before its first argument.
Examples:
(store (data i j) (plus i j))
(store (sine-values (fix (*$ x 100.0)))
(sin x))
arraydims SUBR 1 arg
(arraydims 'x), where x is an array, returns a list of the type
and bounds of x. Thus if x was defined by (array x t 10 20),
(arraydims 'x) => (t 10 20)
Page 78 9. 11/18/73
Functions Concerning Arrays
***** ROUGH DRAFT #9905 *****
bltarray SUBR 2 args
Bltarray is used to copy one array into another.
(bltarray x y) moves the contents of the array x into the
contents of the array y. If x is bigger than y, it is truncated.
If x is smaller than y, the rest of y is unchanged. x and y must
evaluate to atomic symbols which have array properties.
fillarray subr 2 args
(fillarray <array> <list>) fills the array with consecutive items
from the list; thus fillarray could have been defined by:
(defun fillarray (a x)
(do ((x x (cdr x)) ((n 0 (1+ n)))
((null x))
(store (a n) (car x))
))
If the array is too short to contain all the items in the list,
the extra items are ignored. (This is not reflected in the LISP
definition above.) If the list is too short to fill up the
array, the last element of the list is used to fill each of the
remaining slots in the array. An additional flaw in the LISP
definition is that fillarray will work with arrays of more than
one dimension, filling the array in row-major order. fillarray
returns its first argument.
listarray SUBR 1 arg
(listarray <array-name>) takes the elements of the array
specified by <array-name> and returns them as the elements of a
list. The length of the list is the size of the array and the
elements are present in the list in the same order as they are
stored in the array, starting with the zeroth element.
*********************************************************************
*********************************************************************
********* *********
********* TO BE SUPPLIED *********
********* loadarrays.runoff *********
********* *********
*********************************************************************
*********************************************************************
11/18/73 9. Page 79
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
*********************************************************************
*********************************************************************
********* *********
********* TO BE SUPPLIED *********
********* dumparrays.runoff *********
********* *********
*********************************************************************
*********************************************************************
Page 80 9. 11/18/73
"Mapping" Functions
***** ROUGH DRAFT #9905 *****
10. "Mapping" Functions
Mapping is a type of iteration in which a function is successively
applied to pieces of a list. There are several options for the way in
which the pieces of the list are chosen and for what is done with the
results returned by the applications of the function.
For example, mapcar operates on successive elements of the list.
As it goes down the list, it calls the function giving it an element
of the list as its one argument: first the car of the list, then the
cadr, then the caddr, etc.; continuing until the end of the list is
reached. The value returned by mapcar is a list of the results of the
successive calls to the function.
An example of the use of mapcar would be mapcar'ing the function
abs on the list (1 -2 -4.5 6.0e15 -4.2). The result is (1 2 4.5
6.0e15 4.2).
The form of a call to mapcar is
(mapcar f x)
where f is the function to be mapped and x is the list over which it
is to be mapped. Thus the example given above would be written as
(mapcar 'abs
'(1 -2 -4.5 6.0e15 -4.2))
This has been generalized to allow a form such as
(mapcar f x1 x2 ... xn)
In this case f must be a function of n arguments. Mapcar will proceed
down the lists x1, x2, ..., xn in parallel. The first argument to f
will come from x1, the second from x2, etc. The iteration stops as
soon as any of the lists becomes exhausted.
There are five other mapping functions besides mapcar. Maplist is
like mapcar except that the function is applied to the list and
successive cdr's of that list rather than to successive elements of
the list. Map and mapc are like maplist and mapcar respectively
except that the return value is the first of the lists being mapped
over and the results of the function are ignored. Mapcan and mapcon
are like mapcar and maplist respectively except that they combine the
results of the function using nconc instead of list.
Sometimes a do or a straight recursion is preferable to a map;
however, the mapping functions should be used wherever they naturally
apply because this increases the clarity of the code.
Often f will be a lambda-type function rather than the
atomic-symbol name of a function. For example,
11/18/73 10. Page 81
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
(mapcar '(lambda (x) (cons x something)) some-list)
The functional argument to a mapping function must be acceptable to
apply: it cannot be a macro. A fexpr or an fsubr may be acceptable
however the results will be bizarre. For instance, mapping set works
better than mapping setq, and mapping cond is unlikely to be useful.
It is permissible (and often useful) to break out of a map by use
of a go, return, or throw in a lambda-type function being mapped.
Consider this function which is similar to and, except that it works
on a list.
(defun andl (x)
(prog nil ;prog just used so return will work
(mapc (function (lambda (y)
(or y (return nil)) ))
x)
(return t)
))
Here is a table showing the relations between the six map
functions.
applies function to
| successive | successive |
| sublists | elements |
---------------+--------------+---------------+
its own | | |
second | map | mapc |
argument | | |
---------------+--------------+---------------+
list of the | | |
returns function | maplist | mapcar |
results | | |
---------------+--------------+---------------+
nconc of the | | |
function | mapcon | mapcan |
results | | |
---------------+--------------+---------------+
map LSUBR 2 or more args
The first argument to map is a function, and the remaining
arguments are lists. Map "goes down" the lists, applying the
function to the lists each time. The value returned by map is
its second argument. Map stops as soon as one of the lists is
exhausted. Example:
(map '(lambda (x y z) (print (list x y z)))
Page 82 10. 11/18/73
"Mapping" Functions
***** ROUGH DRAFT #9905 *****
'(1 2 3 4) '(a b c d e) '(+ - * |))
prints
((1 2 3 4) (a b c d e) (+ - * |))
((2 3 4) (b c d e) (- * |))
((3 4) (c d e) (* |))
((4) (d e) (|))
and returns (1 2 3 4).
mapc LSUBR 2 or more args
Mapc is just like map except that the function is applied to
successive elements of the lists rather than to the lists
themselves. Thus the example given under map would print
(1 a +)
(2 b -)
(3 c *)
(4 d |)
and return (1 2 3 4)
mapcar LSUBR 2 or more args
Mapcar is like mapc except that the return value is a list of the
results of each application of the function. Thus the example
given with mapc would return, not (1 2 3 4), but
((1 a +) (2 b -) (3 c *) (4 d |))
maplist LSUBR 2 or more args
Maplist is like map except that the return value is a list of the
results of each application of the function. Thus the example
given with map would return, not (1 2 3 4), but
(((1 2 3 4) (a b c d e) (+ - * |)) ((2 3 4) (b c d e) (- * |))
((3 4) (c d e) (* |)) ((4) (d e) (|)))
mapcan LSUBR 2 or more args
Mapcan is like mapcar except that the values returned by the
function are nconc'ed together instead of being listed together.
Thus the example would return
(1 a + 2 b - 3 c * 4 d |)
11/18/73 10. Page 83
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
mapcon LSUBR 2 or more args
Mapcon is like maplist except that the values returned by the
function are nconc'ed together instead of being listed together.
This can have disastrous effects on the arguments to mapcon if
one is not careful. The example would return
((1 2 3 4) (a b c d e) (+ - * |) (2 3 4) (b c d e) (- * |)
(3 4) (c d e) (* |) (4) (d e) (|))
Page 84 10. 11/18/73
Sorting Functions
***** ROUGH DRAFT #9905 *****
11. Sorting Functions
Several functions are provided for sorting arrays and lists. These
functions use algorithms which always terminate no matter what sorting
predicate is used, provided only that the predicate always terminates.
These sorts are not necessarily stable, that is equal items may not
stay in their original order.
After sorting, the argument (be it list or array) is rearranged
internally so as to be in complete order. In the case of an array
argument, this is accomplished by permuting the elements of the array,
while in the list case, the list is reordered by rplacd's in the same
manner as nreverse. Thus if the argument should not be clobbered, the
user should sort a copy of the argument, obtainable by bltarray or
subst, as needed.
Should the comparison predicate cause an error, such as a wrong
argument type error, the result of the sort up to that point is not
guaranteed, unless the appropriate replacement for the bad argument is
supplied by the user interrupt handler.
Both sort and sortcar handle the case in which their second
argument is the function alphalessp in a more efficient manner than
usual. This efficiency is primarily due to elimination of argument
checks at comparison time.
sort SUBR 2 args
The first argument to sort is an S-expression array, the
second a predicate of two arguments. The domain of the predicate
must include all objects in the array; thus if the array contains
only atomic symbols, the predicate need only apply to atomic
symbols, but if the array also contains S-expressions, the
predicate must apply to them also. The predicate should take two
arguments, and return non-nil if and only if the first argument
is strictly less than the second (in some appropriate sense).
The sort function proceeds to sort the contents of the array
under the ordering imposed by the predicate, and returns its
first argument. Note that since sorting requires many
comparisons, and thus many calls to the predicate, sorting will
be much faster if the predicate is a compiled function rather
than interpreted.
11/18/73 11. Page 85
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
Example: (defun mostcar (x)
(cond ((atom x) x)
((mostcar (car x)))))
(sort fooarray
(function (lambda (x y)
(alphalessp (mostcar x) (mostcar y)))))
If fooarray contained these items before the sort:
(tokens (the lion sleeps tonight))
(carpenters (close to you))
((rolling stones) (brown sugar))
((beach boys) (i get around))
(beatles (i want to hold your hand))
then after the sort fooarray would contain:
((beach boys) (i get around))
(beatles (i want to hold your hand))
(carpenters (close to you))
((rolling stones) (brown sugar))
(tokens (the lion sleeps tonight))
sortcar SUBR 2 args
sortcar is exactly like sort, but the items in the array
should all be non-atomic. sortcar takes the car of each item
before handing two items to the predicate. Thus sortcar is to
sort as mapcar is to maplist.
Page 86 11. 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
12. Functions for Controlling the Interpreter
12.1 The Top Level Function
When LISP is at its "top level," it continually evaluates some
form. Normally this form is
(setq * (print (eval (read))))
which causes a "read-eval-print loop," i.e. each S-expression that is
typed in gets evaluated and the value is printed, then the next
S-expression is read. It is possible for the user to change the top
level form to perform some other action at top level. See the sstatus
function (section 12.7).
When the LISP subsystem is entered, it is at top level. At this
time, a * is typed out and LISP begins continually evaluating the top
level form. LISP can return to top level from the middle of one of
these evaluations when an error occurs. Generally errors do not
immediately return to top level; rather they give the programmer a
chance to debug the error. However, if an error is not corrected it
will eventually get to top level unless there is an errset (page 44)
in the way. When LISP returns to its top level, it again types a *
and begins continuously evaluating the top level form.
errlist VARIABLE
The value of errlist is a list of forms which are evaluated when
control returns to top level either because of an error or when
an environment is initially started. This feature is used to
provide self-starting LISP environments and to provide special
error handling for subsystems written in LISP.
11/18/73 12.1 Page 87
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
* VARIABLE
The value of * is the result of the last evaluation performed at
top level or in a break loop. When the lisp environment is first
entered and when control is returned to top level from an error,
the value of * is * itself.
Example of use:
(Lines preceded with a >>> are user input, others are
system typeout)
;bkpt some-kind-of-lossage
>>> (evalframe nil) ;get uppermost evalframe
(-46573536345 (foo x y) -53635473537)
>>> (evalframe (car *)) ;get preceding evalframe
(-46573536214 (barf (quote lose!!) 2) -53635473422)
Page 88 12.1 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
12.2 Break Points
break FSUBR
(break <tag> <pred>) evaluates <pred>, but not <tag>. If the
value of <pred> is not nil, the state of the I/O system is saved,
";bkpt <tag>" is typed out, and control returns to the terminal.
We say that a "break loop" has been entered. <tag> may be any
object. It is used only as a message typed out to identify the
break. It is not evaluated.
S-expressions may be typed in and evaluated as at top level.
Break does an errset so that errors cannot cause an abnormal
return from the break.
If $p is typed in, break returns nil. This "$p" is <dollar> p
<newline> in the Multics implementation, but <altmode> P <space>
in the pdp-10 implementations.
If (return x) is typed in, break evaluates x and returns that
value. When break returns, the state of the I/O system is
restored.
Break can be used to allow user intervention in a program when
something unexpected happens. It is used in this way by the LISP
error system.
(break <tag> <pred> <form>) is the same as (break <tag> <pred>)
except that if $p is typed, the <form> is evaluated and used as
the value of the break instead of nil.
11/18/73 12.2 Page 89
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
12.3 Control Characters
LISP can be directed to take certain actions by entering "control
characters." The difference between control characters and normal
input is that control characters take effect as soon as they are
entered while normal input only takes effect when LISP asks for it, by
use of functions such as read, or by being in the top level
read-eval-print loop or in a break loop.
Control characters can be typed in from the terminal according to
some procedure that depends on the implementation. They can also by
"typed in" by a program using the function ioc.
Although control characters are usually processed as soon as they
are typed, they will be delayed if there is a garbage collection in
progress or LISP is in (nointerrupt t) mode - see the nointerrupt
function.
Entering Control Characters in ITS LISP
In the pdp-10/ITS implementation of MACLISP, control characters are
entered by means of the "CTRL" key on the terminal. For example,
CTRL/G is entered by holding down "CTRL" and striking the "G" key.
Control characters echo as an uparrow or circumflex followed by the
character. Numbers may not be used as control characters.
Entering Control Characters in DEC-10 LISP
Control characters may be entered in the same way as in ITS LISP if
LISP is currently (read)'ing from the terminal. If a LISP program is
actively running, it is necessary to first gain its attention by
striking ctrl/C. LISP rings the bell and types a ? and an upparrow,
prompting for the entry of a character to be treated as a control
character. If you type a second ctrlC control will return to the
monitor.
Page 90 12.3 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
Entering Control Characters in Multics LISP
In the Multics implementation of MACLISP, one signals one's desire
to enter a "control" character by hitting the "attention" key on the
terminal. This is called "break," "interrupt," "quit," etc. on
different terminals. This causes lisp to type out "CTRL/" After this
has been typed, you may type one control character, which is a letter
from the list in section 12.3.3 which will be interpreted to have its
"control" meaning.
You may also enter a number, which will be interpreted in decimal.
A user interrupt will be issued on the user interrupt channel
indicated by the number you typed in. If there is no such interrupt,
or the interrupt service function for that channel is nil, no warning
will be issued. The argument passed to the interrupt service function
is the atom ioc. The most useful interrupt channel numbers are 0,
which is the same as CTRL/\@; 1, which is the same as CTRL/h, and 2
which is the same as CTRL/a (exactly).
Note: any input that has been typed in but has not yet been read by
lisp when the attention button is pushed will be lost. Usually this
is the current line unless Multics happens to be running slow.
It is also possible to enter "control" characters from an input
character stream, which may have its source at the terminal or in a
file, without the use of the "attention" key. The desired control
character is prefixed by a \036 character, also known as \r or
"control up-arrow." If two of these prefix characters occur together,
one \036 character is read and no "control" action is performed.
Otherwise, the character following the \036 is processed as a control
character, then reading continues. This method only works with the
letter and special-symbol control characters, but not with the number
control characters.
NB: Control characters will be accepted in upper or lower case. All
characters other than those with defined meanings are rejected with an
error message. Only one control character may be entered at a time.
When a "user interrupt" is caused, if the interrupt is not enabled
nothing happens. If the interrupt is enabled, then a user-specified
function is called. The interrupt may be enabled by using the
function sstatus. E.g.: (sstatus interrupt 2 'f00) causes f00 to be
called with one argument when interrupt 2 occurs.
Example:
(system output is underlined, user input is not)
(defun loop (x) (loop (add1 x)))
loop
(loop 0)
function runs for a long time,
<ATTN> then user hits attention button.
CTRL/B
;bkpt↑b system enters break loop
11/18/73 12.3 Page 91
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
x user looks at value of x
4067
<ATTN> user hits attention button again
CTRL/G and returns to top level
Quit
*
Page 92 12.3 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
12..3 Control Characters That Have Been Defined
These are the control characters that have defined meanings
A increments the value of the atom ↑a and causes user
interrupt 2.
B causes user interrupt number 1, which (usually) enters the
"bkpt ↑b" breakpoint.
C sets the atom ↑d to nil, turning off garbage collector
messages
D sets the atom ↑d to t, turning on garbage collector messages
G quits back to top level of lisp, unwinding all bindings
Q sets the atom ↑q to t, enabling input from the source
selected by the value of infile, or by use of the function
uread.
R sets the atom ↑r to t, enabling output to the destinations
selected by the value of outfiles, or by use of the uwrite
function.
U causes the current call to (read) to be restarted from the
beginning.
S sets the atom ↑q to nil, enabling input from the terminal
T sets the atom ↑r to nil, disabling output to the
destinations that CTRL/r enables.
V sets the atom ↑w to nil, enabling output to the terminal
W sets the atom ↑w to t, disabling output to the terminal
X causes an error which can be caught by errset
Z On the pdp-10 returns to DDT. On Multics returns to Multics
command level. (start re-enters lisp) This control character
is handled immediately even when LISP is garbage collecting
or running in (nointerrupt t) mode, unlike most of the
others.
@ causes user interrupt 0. Note that on Multics an escape must
be used to type @ sign.
\ causes user interrupt 14. Note that on Multics an escape
must be used to type this backslash character.
11/18/73 12..3 Page 93
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
] causes user interrupt 15.
↑ causes user interrupt 16.
The following control characters only exist in the Multics
implementation.
. does nothing, used to speed up slow process by causing an
interaction. This control character is handled immediately
even when LISP is garbage collecting or running in
(nointerrupt t) mode, unlike most of the others.
? asks the LISP subsystem what it is doing: running, waiting
for input, collecting garbage, or running with
user-interrupts masked off. This control character is
handled immediately even when LISP is garbage collecting or
running in (nointerrupt t) mode, unlike most of the others.
The following control characters only exist in pdp-10
implementations with the "moby I/O" capability.
F cause display slave to seize a display.
N turn on display.
O turn off display.
Y interrogate display slave.
The following control characters only work in the pdp-10
implementation.
K redisplay the current input. allows you to get a clean copy
of your input after rubouts have been used.
L erases the screen if using a display terminal, then does a
control k.
U if using a display terminal, and in (sstatus pagepause t)
mode, and the end of the screen has been reached, typing
control u will erase the screen and allow lisp to continue
typing out.
Page 94 12..3 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
12..4 Control-Character Functions
ioc FSUBR
The argument to ioc is processed as if it were a "control
character" that had been typed in. Numbers are taken as a whole,
pname atoms (atomic symbols) are processed character by
character, except that nil causes an immediate return. Examples:
(ioc 1) causes user interrupt 1.
(ioc vt) switches output to the terminal.
(ioc q) switches input to a file.
(ioc g) quits back to the top level of lisp.
If ioc returns, its value is t.
iog FSUBR
iog saves the values of the I/O switches ↑q, ↑r, and ↑w. Then it
processes its first argument the same as ioc. Next the remaining
arguments to iog are evaluated, from left to right. The values
of the variables ↑q, ↑r, and ↑w are restored, and the value of
the last argument is returned. Example:
(iog vt (princ "A Message."))
gets a message to the console no matter what the I/O system is
doing. It evaluates to "A Message."
↑a VARIABLE
When a CTRL/a is done, the value of the atom ↑a is incremented
(user interrupt 2 is also signalled.) If ↑a is not a number, it
is set to 0.
11/18/73 12..4 Page 95
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
12.4 Errors and User Interrupts
12.4.1 The LISP Error System
The errors detected by the LISP subsystem are divided into two
types: correctable and uncorrectable. The uncorrectable errors will
be explained first since they are simpler.
An uncorrectable error is an error that causes the destruction of
the evaluation in which it occurs. An example of an uncorrectable
error is illegal format in a 'do'. When an uncorrectable error
occurs, the first thing that happens is the printing of an error
message. The error message goes to the terminal and nowhere else, no
matter how the I/O switches and variables are set. (The CTRL/B
feature is an exception to this. See section 12.3.3) The error
message consists of some explanatory text and (sometimes) the object
that caused the error.
After the error message has been printed, control is returned to
the most recent error-catcher. There is an error-catcher at top
level, and error-catchers are set up by the functions errset and
break. All variable bindings between the error-catcher and the point
where the error occurred are restored. Thus all variables are
restored to the values they had at top level or at the time the errset
was done, unless they were setq'ed without being bound.
What happens next depends on how the error-catcher was set up. At
top level, (mapc 'eval errlist) is done, a * is typed, and the
read-eval-print loop (or a user specified top level form) is
re-entered. If an error returns to break, it simply re-enters its
read-eval-print loop. In the Multics implementation the fact that
break has caught an error is signalled by doing something to the
terminal such as blinking a light or spinning the typeball, depending
on the type of terminal. If an error returns to errset, errset
returns nil and evaluation proceeds.
The above description is slightly simplified. It is possible for a
user interrupt to occur between the typing of the message and the
unwinding of bindings and return of control to an error-catcher. This
user interrupt is normally a break loop which allows the user to
examine the values of variables before the bindings are restored, in
hope of finding the cause of the error. If the error is going to
return to top level, the *rset-trap user interrupt (number 19.) is
signalled. In (*rset t) mode a break loop is entered, but in (*rset
nil) mode the user interrupt is ignored by the system supplied
handler. If the error is going to return to a break or an errset, the
errset user interrupt (number 4) is signalled. The initial
environment contains a null handler for this interrupt, but the user
may supply a break loop or other handler.
Correctable errors are errors which may be corrected by user
Page 96 12.4.1 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
intervention. If such an error is correctly corrected, evaluation
will proceed as if no error had occurred. If the option to correct
the error is not exercised, this type of error will be handled the
same as an uncorrectable error.
When a correctable error occurs, a user interrupt is signalled.
See section 11.4.2 for user interrupt channel assignments for these
errors. The initial environment contains handlers for these errors
which print an error message similar to the message printed for an
uncorrectable error and then enter a break loop.
The argument passed to the user interrupt handler is usually a list
describing the error. See section 11.4.2 for details. If the user
interrupt handler is nil, or if it returns a non-list, the error is
treated like an uncorrectable error. But if the handler returns a
list, the car of that list is used to correct the error in a way which
depends on the particular error which occurred.
If the most recent error-catcher is an errset or a break,
correctable errors will be treated as uncorrectable errors unless
there is a non-null handler for user interrupt 4, the errset
interrupt. This is to prevent confusing "recursive" error breaks
unless the user indicates that he is sophisticated by setting up a
handler for the errset interrupt.
11/18/73 12.4.1 Page 97
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
12.4.2 User Interrupts
LISP provides a number of "user interrupts," which are a mechanism
by which a user procedure may temporarily gain control when an
exceptional condition happens. The exceptional conditions that use
the user interrupt system include certain control characters, the
alarmclock timers, the garbage collector, and many of the errors that
are detected by the interpreter or by the system functions.
The user interrupts are divided up into several channels. Each
channel is designated by a number. Each channel has associated with
it a "service function." If the service function is nil, interrupts
on that channel will be ignored. If the service function is not nil,
it is a function which is called with one argument when the
user-interrupt occurs. The nature of the argument depends on which
channel the interrupt is on; usually it is an S-expression which can
be used to localize the cause of the interrupt. Some user interrupts
use the value returned by the service function to decide what to do
about the cause of the interrupt.
The service function for user interrupt channel n can be obtained
by (status interrupt n). It can be set by (sstatus interrupt n f).
The initial values for the service functions of the various interrupts
are provided by the system as break loops for some interrupt channels
and nil for others.
Some user interrupt channels keep their service functions as the
values of variables accessible to the user; this allows them to be
lambda-bound. See 12.4.3.
The interrupt channels with entries in the return value column of
the table of user interrupts included in this section are user
interrupts signalled by correctable error conditions. The argument to
the service function is a description of the error in the form shown.
If the service function returns nil (or any atom), the normal error
procedure occurs -- control returns to the most recent errset or to
top level if there was no errset. If the service function returns a
list, it is interpreted as the form shown in the return value column.
The car of the list is used to attempt recovery from the error. If
recovery is successful execution proceeds from the point where the
error occurred. If recovery is unsuccessful another error is
signalled. If a quote (') is shown in the return value column, it
means that the car of the list returned by the service function will
be evaluated before it is used.
Page 98 12.4.2 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
Table of User Interrupt Channels
Chn Serv. Fcn. Reason Arg to Return
Num Val. Atom for intr Serv. Fcn. Value
--- --------- -------- --------- -----
0 none ctrl @ nil -
1 ↑b ctrl b nil -
2 none ctrl a nil -
3 alarmclock timer went 'time or
off. 'runtime -
4 errset error was caught nil -
by errset.
5 undf-fnctn undefined fcn (fcn) (new-fcn)
6 unbnd-vrbl undefined atom (atom) ('new-value)
7 wrng-type-arg a fcn didn't (bad-val) (new-val)
like its arg.
8. unseen-go-tag go or throw lost (bad-tag) (new-tag)
9. wrng-no-args wrong num of arg (form args-prop) or
(form lambda-list) or
nil ('new-form)
10. gc-lossage no more core ? ?
11. fail-act misc. error. see below see below
14. none ctrl \ nil -
15. none ctrl ] nil -
16. none ctrl ↑ nil -
18. none autoload (fcn . prop) -
19. *rset-trap error return nil -
to top level
20. gc-daemon a garbage ? -
collection
occurred.
11/18/73 12.4.2 Page 99
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
The fail-act interrupt, number 11., is used for a variety of
miscellaneous error conditions. Here is a table giving the types of
arguments that may be passed to the fail-act service function. For
each type the cause of the interrupt and the return value to correct
the error are given.
(arrayindex (name indices...)) An out-of-bounds array access occurred
on the array name. Sometimes it is not possible to determine the
name of the array, in which case name will be ?. For example,
this can happen if the array has been remob'ed. The return form
is ((name subs....)) which will retry the access with the new
subscripts subs.... name is ignored.
(go return) go or return was used outside of a prog. The return value
does not matter; this error is not correctable.
(arg (n)) The arg function was called with argument n, but this was
not done inside a lexpr.
(setarg (n value)) The function setarg was called with arguments n and
value and an error similar to the preceding occurred.
(ibase) The reader variable ibase had a bad value: not a fixnum or
not between 2 and 36. It is reset to 8. before the user
interrupt occurs. Returning (t) will cause the reader to
continue reading.
(base) The printer variable base had a bad value: not a fixnum or not
between 2 and 36. It is reset to 8. before the user interrupt
occurs. Returning (t) will cause the printer to continue.
(infile x) The input file x is invalid for one reason or another. ↑q
has been reset to nil. If (t) is returned by the service
function, ↑q will be set back to t and the function that lost
trying to input from x will proceed, taking input from infile.
(setq (nil)) You aren't allowed to change the value of nil.
(read-eof) The reader found an end of file in the middle of an object.
Usually this indicates mismatched parentheses. If (t) is
returned, it will go on reading the broken object from whatever
input source is now selected.
(outfile x) The output file x is invalid for one reason or another.
↑r is reset to nil before the user interrupt occurs. If (t) is
returned, ↑r will be set back to t and the function that lost
trying to output to x will go on its way.
(filepos x) The filepos function was used on the file x, but this file
is not equipped for random access. If ('new-val) is returned,
filepos returns new-val to its caller without further ado.
Page 100 12.4.2 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
(filepos x n) The filepos function was used in the form (filepos x n),
but n is not a position inside the file x. If ('new-val) is
returned, filepos returns new-val to its caller without further
ado.
(openi x), (openo x), (opena x), (rename x y), (deletef x) The file
system complained in some way: e.g. file not found, incorrect
access. The argument passed to the service function represents
the form which was evaluated to cause the error, except that the
values of the arguments are the values they have after being
mergef'ed over the defaults, i.e. they are precise namelists. If
('new-val) is returned, the function that lost returns new-val as
its value without further ado.
11/18/73 12.4.2 Page 101
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
12.4.3 User Interrupt Functions and Variables
alarmclock SUBR 2 args
alarmclock is a function for controlling timers. It can start
and stop two seperate timers; one is a real-time timer and the
other is a cpu-time timer. The first argument to alarmclock
indicates which timer is being referred to: it may be the atom
time to indicate the real-time timer or the atom runtime to
indicate the cpu-time timer.
The second argument to alarmclock controls what is done to the
selected timer. If it is a positive (non-big) number the timer
is started. Thus if n is a positive fixnum or flonum,
(alarmclock 'time n) sets the real-time timer to go off in n
seconds, and (alarmclock 'runtime n) sets the cpu-time timer to
go off in n microseconds. If the timer was already running the
old setting is lost. Thus at any given time each timer can only
be running for one alarm, but the two timers can run
simultaneously.
If the second argument to alarmclock is not a positive number,
the timer is shut off, so (alarmclock x nil) or (alarmclock x -1)
shuts off the timer.
alarmclock returns t if it starts a timer, nil if it shuts it
off.
When a timer goes off, user interrupt 3 occurs. The service
function is run in (nointerrupt t) mode so that it can not be
interrupted until it has done its thing. If it wants to allow
interrupts, other timers, etc. it can go (nointerrupt nil). In
any case the status of the nointerrupt flag will be restored when
the service function returns. The argument passed to the user
interrupt service function is a list of one element, the atom
time or the atom runtime, depending on the first argument in the
call to alarmclock that set up the timer. See also the function
nointerrupt.
alarmclock VARIABLE
The value of alarmclock is the service function for user
interrupt number 3, which is the user interrupt signalled when a
timer set up by the alarmclock function goes off.
Page 102 12.4.3 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
nointerrupt SUBR 1 arg
(nointerrupt t) shuts off LISP interrupts. This prevents
alarmclock timers from going off and prevents the use of control
characters such as CTRL/g and CTRL/h. Any of these interrupts
that occur are simply saved. (nointerrupt t) mode is used to
protect critical code in large subsystems written in LISP. It is
also used by the LISP subsystem itself to protect against
interrupts in the garbage collector.
(nointerrupt nil) turns interrupts back on. Any interrupts which
were saved will now get processed.
Nointerrupt returns the previous state of the interruptdisable
switch, t or nil. The normal, initial state is nil.
errset VARIABLE
The value of the atom errset is the service function for user
interrupt number 4, which is signalled when an error is caught by
an errset.
fail-act VARIABLE
The value of fail-act is the service function for user interrupt
number 11., which is signalled when any of a large variety of
miscellaneous error conditions occurs.
gc-daemon VARIABLE
The value of gc-daemon is the service function for user interrupt
20., which is signalled after each garbage collection.
gc-lossage VARIABLE
The value of gc-lossage is the service function for user
interrupt number 10., which is signalled when there is no more
memory. In the Multics implementation, there is always enough
memory, so this user interrupt never occurs.
11/18/73 12.4.3 Page 103
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
unbnd-vrbl VARIABLE
The value of unbnd-vrbl is the service function for user
interrupt number 6, which is signalled when an attempt is made to
evaluate an atomic symbol which does not have a value (an unbound
variable.)
undf-fnctn VARIABLE
The value of undf-fnctn is the service function for user
interrupt number 5, which is signalled when an attempt is made to
call an undefined function.
unseen-go-tag VARIABLE
The value of unseen-go-tag is the service function for user
interrupt 8., which is signalled when go or throw is used with a
tag which does not exist in the current prog body or in any
catch, respectively.
wrng-no-args VARIABLE
The value of wrng-no-args is the service function for user
interrupt channel 9., which is signalled when a function is
called with the wrong number of arguments.
wrng-type-arg VARIABLE
The value of wrng-type-arg is the service function for user
interrupt number 7, which is signalled when an argument is passed
to a system function which is not acceptable to that function.
*rset-trap VARIABLE
The value of *rset-trap is the service function for user
interrupt 19., which is signalled when an error returns control
to top level, just before the bindings are restored.
Page 104 12.4.3 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
12.4.4 Autoload
The "autoload" feature provides the ability for a function not
present in the environment to be automatically loaded in from a file
the first time it is called. When eval, apply, funcall, or the
version of apply used by compiled LISP searches the property list of
an atom looking for a functional property, if the first functional
property found is under the indicator autoload, automatic loading will
occur.
Automatic loading is performed by means of user-interrupt 18.; thus
the user may assert any desired degree of control over it. When the
autoload property is encountered, the user-interrupt 18. handler is
called with one argument, which is a dotted pair whose car is the
atomic symbol which is the function being autoload'ed, and whose cdr
is the value of the autoload property. The system-supplied handler
for user interrupt 18. could have been defined by:
(sstatus interrupt 18.
'(lambda (x)
(apply (function fasload) (cdr x))))
When the interrupt handler returns, it had better have put a
functional property on the property list of the function being
autoloaded. If not, an undf-fnctn error will occur with a message
such as
"function undefined after autoload"
Note that the functional property must be placed on the property list
before the autoload property. This is normally the case.
Examples of setting up functions to be autoloaded:
In the Multics implementation:
(putprop 'foo ">udd>AutoProg>Library>foo-function" 'autoload)
In the ITS implementation:
(putprop 'foo '(foo fasl dsk me) 'autoload)
11/18/73 12.4.4 Page 105
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
12.5 Debugging
12.5.1 Binding, Pdl Pointers, and the Evaluator
The Maclisp evaluator is conceptually based on a push down list
(pdl), or stack, which holds bindings, evaluation frames, and sundry
internal data. Bindings are values of atomic symbols which are saved
when the symbols are used as lambda variables, prog variables, or do
variables. Evaluation frames are constructed when a non-atomic form
is evaluated or when apply is used. They correspond to function
calls.
As the evaluator recursively evaluates a form, information is
pushed onto the pdl and later popped off. When the *rset, nouuo, and
noret flags are t this information is sufficiently detailed to be of
use in debugging. (See the functions *rset, nouuo, and noret.) A
position within the pdl may be named by means of a "pdl pointer,"
which is a negative fixnum whose value has meaning to the evaluator.
Pdl pointers may be used as arguments to several debugging functions
decsribed in the next section.
There are several ways to obtain a pdl pointer. Since the fixnum
value of a pdl pointer has only internal meaning, generally a pdl
pointer cannot be obtained from user input. Several of the debugging
functions described in the next section generate pdl pointers.
An important thing to note about pdl pointers is their limited
scope of validity. If the information on the pdl which is named by a
pdl pointer has been popped off since the pdl pointer was created, the
pdl pointer no longer has valid meaning.
Page 106 12.5.1 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
12.5.2 Functions for Debugging
*rset SUBR 1 arg
(*rset x) sets the *rset flag to nil if x is nil, to t if x is
non-nil, and returns the value it set it to. If the *rset flag
is t, extra information is kept by the interpreter to allow the
debugging functions, such as baktrace and evalframe, to work.
baktrace LSUBR 0 to 2 args
baktrace displays the stack of pending function calls. It only
works in (*rset t) mode. The first argument is a pdl pointer, as
with evalframe. If it is omitted, nil is assumed, which means
start from the top of the pdl. The second argument is the
maximum number of lines to be typed; if it is omitted the entire
stack is displayed.
errframe SUBR 1 arg
Errframe returns a list describing an error which has been
stacked up because of a user interrupt. The list has the form
(pdlptr message alist), where pdlptr is a number which describes
the location in the pdl of the error, message is a character
string which can be printed out as a description of the error,
and alist is a number which can be used as a second argument to
eval or a third argument to apply to cause evaluation using the
bindings in effect just before the error occurred.
The argument to errframe can be nil, which means to find the
error at the top of the stack; i.e. the most recent error. It
can also be a pdl ptr, in which case the stack is searched
downward from the indicated position. Thus the second most
recent error may be found by:
(errframe (car (errframe nil)))
The argument to errframe may also be a positive number, which is
the negative of a pdl ptr. This means start from the position in
the stack marked by the pdl ptr and search upwards.
If no error is found, errframe returns nil.
11/18/73 12.5.2 Page 107
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
errprint SUBR 1 arg
Errprint treats its argument the same as errframe. The message
portion of the error frame is princ'ed. Errprint returns t if a
message was typed out and nil if no error frame was found.
evalframe SUBR 1 arg
The argument to evalframe is a pdl ptr, as with errframe. The
pdl is searched for an evaluation of a function call, using the
same rules about starting point and direction as errframe uses.
Evalframe always skips over any calls to itself that it finds in
the pdl.
The value is a list (pdlptr form alist), where pdlptr is a pdl
pointer to the evaluation in the stack, suitable for use as an
argument to evalframe or errframe or baktrace, form is the form
being evaluated or the name of the function being applied, and
alist is an a-list pointer which can be used with eval to
evaluate something in the binding context just before the
evaluation found by evalframe.
Evalframe returns nil if no evaluation can be found.
Evalframe only works in (*rset t) mode.
freturn SUBR 2 args
(freturn p x) returns control to the evaluation designated by the
pdl pointer p, and forces it to return x. This "non-local-goto"
function can be used to do fancy recovery from errors.
See also Chapter 14, on the trace package.
The following functions only exist in the Multics implementation.
baktrace1 LSUBR 0 to 2 args
Baktrace1 is the same as baktrace except that a-list ptrs
suitable for use with eval and apply are displayed along with the
function names.
Page 108 12.5.2 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
baktrace2 LSUBR 0 to 2 args
Baktrace2 is the same as baktrace1 except that pdl pointers,
suitable for use with baktrace and evalframe, are displayed along
with the function names and a-list pointers.
11/18/73 12.5.2 Page 109
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
12.5.3 An Example of Debugging in Maclisp
*********************************************************************
*********************************************************************
********* *********
********* TO BE SUPPLIED *********
********* debuggingexample.runoff *********
********* *********
*********************************************************************
*********************************************************************
Page 110 12.5.3 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
12.6 Garbage Collection
Garbage collection is the mechanism which LISP uses to control
storage allocation. Whenever LISP feels that too much storage is
being used, a garbage collection is initiated. The garbage collector
traces through all the S-expressions which can be reached by car'ing
and cdr'ing from atomic symbols' values and property lists, from forms
and temporary results currently being used by the evaluator, from data
used by compiled code, and from the saved values of bound variables.
All the data which it finds in this way is "good" data, in that it is
possible for it to be used again. Everything else is garbage, which
can never again be used for anything because it cannot be accessed, so
the storage used by it is reclaimed and reused.
gc FSUBR
(gc) causes a garbage collection and returns nil.
gctwa FSUBR
Gctwa is used to control the garbage collection of "truly
worthless atoms," which are atomic symbols which have no value
and no special properties, and which are not referenced by any
list structure, other than the obarray (the current obarray if
there is more than one).
(gctwa) causes truly worthless atoms to be removed on the next
garbage collection.
(gctwa t) causes truly worthless atoms to be removed on each
garbage collection from now on. Note: gctwa does not evaluate
its argument.
(gctwa nil) causes this continual removal of truly worthless
atoms to be shut off, but it does not affect whether the next
garbage collection removes twa's.
The value returned by gctwa is a fixnum which is 0 if no garbage
collection of truly worthless atoms will be done, 1 if twa's are
to be gc'ed on the next garbage collection, 10 if twa's are to be
gc'ed on all garbage collections, or 11 if both. (These numbers
are octal.)
11/18/73 12.6 Page 111
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
↑d SWITCH
If the value of ↑d is non-nil, the garbage collector prints an
informative message after each garbage collection.
See also the variables gc-daemon (page 103) and gc-lossage (page 103).
Page 112 12.6 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
12.7 The Functions status and sstatus
status FSUBR
The status function is used to get the value of various system
variables. Its first argument, not evaluated, is an atomic
symbol indicating which of its many functions status should
perform. The use of additional arguments depends on what the
first argument is. Omitted arguments are assumed to be nil. The
following "status functions" exist:
STATUS FUNCTIONS FOR THE I/O SYSTEM
Note: in the following, c represents an argument specifying a
character. If c is non-atomic it is evaluated. The value must
be a fixnum which is the ascii code for a character. If c is
atomic it is not evaluated. It may be a fixnum or a character
object.
(status ioc c) gives the state (t or nil) of the
control-"c"-switch. For example, (status ioc q) is t if input is
from a file, nil if input is from the terminal.
(status uread) returns a 4-list for the current uread input
source, or nil if uread is not being done.
(status uwrite) returns the corresponding list for the current
uwrite output destination.
(status crunit) returns a 2-list of the current unit; i.e.
device and directory.
(status crfile) returns a 2-list giving the file names for the
current file in the "uread" I/O system.
(status tabsize) returns the number of character positions
assumed between tab stops.
(status charmode f) returns the value of the character-mode
switch for the file object f. If f is nil or omitted the
terminal is assumed. If this switch is t (the normal case for
the terminal) output is sent to the device as soon as it is
generated. If the switch is nil (the normal case for files other
than the terminal) output is held until a newline is typed, an
error occurs, input is requested, or the buffer becomes full.
This provides increased efficiency at the cost of not immediately
seeing all output.
11/18/73 12.7 Page 113
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
STATUS FUNCTIONS FOR THE READER
See sections 12.1.2 and 12.6.2 for a description of how the data
examined by these functions is used. (status chtran c) gets the
character translation table entry for the character c. This is
the ascii code of a character substituted for c when it appears
in a pname being read in.
(status syntax c) returns the 18 syntax bits for the character c
as a fixnum.
(status macro c) returns nil if c is not a macro character. If c
is a macro character it returns a list of the macro character
function and the type, which is nil for normal macros and s for
splicing macros.
(status +) gets the value of the + switch (t or nil). This
switch is normally nil. If it is t, atoms more than one
character long beginning with a + or a - are interpreted as
numbers by the reader even if they contain letters. This allows
the use of input bases greater than ten.
(status ttyread) returns the value of the ttyread switch, which
is kept in the readtable. At present this is not used for
anything in the Multics implementation. In the pdp-10
implementation it controls whether tty "force feed" characters
are used.
STATUS FUNCTIONS FOR THE PRINTR
(status terpri) returns the value (t or nil) of the terpri
switch, which is kept in the readtable. This switch is normally
nil. If it is t, the output functions such as print and tyo will
not output any extra newlines when lines longer than linel are
typed out.
(status ) returns the value (t or nil) of the switch, which is
kept in the readtable. If this switch is t, the format for
fixnums with lots of trailing zeroes is not used.
(status abbreviate) returns the value of the abbreviation
control. See section 13.7 for a description of the abbreviation
control.
STATUS FUNCTION FOR THE GARBAGE COLLECTOR
(status gctime) returns the number of microseconds spent
garbage-collecting.
Page 114 12.7 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
STATUS FUNCTIONS FOR CONTROL OF THE EVALUATOR
ENVIRONMENT ENQUIRIES
(status date) returns a 3-list indicating the current date as
(year-1900. month-number day)
(status daytime) returns a 3-list of the 24-hour time of day as
(hour minute second).
(status time) is the same as (time), the number of seconds the
system has been up.
(status runtime) is the same as (runtime), the number of
microseconds of cpu time that has been used.
(status system x) returns a list of the system properties of the
atomic symbol x, which is evaluated. This list may contain subr,
fsubr, macro, or lsubr if x is a function, and value if this
atomic symbol is a system variable.
(status uname) returns an atomic symbol whose pname is the
current user's name. In the Multics implementation this is in
the format User.Project; the dot will be slashified if print is
used to display this.
(status udir) returns the name of the user's directory. In the
ITS implementation this is the same as the user's name as
returned by (status uname). In the Multics implementation this
is the user's default working directory.
(status lispversion) returns the version number of lisp.
(status jcl) returns the "job command line" from ddt in the
pdp-10 implementation. In the Multics implementation it returns
the exploded second argument of the lisp command, or else nil if
the lisp command had only one argument. If lisp was invoked by
lisp environment "foo bar"
(status jcl) => (f o o / b a r)
The following status functions only exist in the Multics
implementation.
(status paging) returns a list of the paging-device page faults
and total page faults that have been incurred.
11/18/73 12.7 Page 115
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
(status arg n) returns the n+1'th argument of the lisp command,
as an interned atomic symbol. Nil is returned if n is more than
the number of arguments on the lisp command.
MISCELLANEOUS STATUS FUNCTIONS
(status toplevel) returns the top-level form, which is
continually evaluated when LISP is at its top level. If this is
nil, a normal read-eval-print loop is used.
(status interrupt n) returns the service function for user
interrupt channel n. n is evaluated.
(status pagepause) returns the value of the pagepause flag. See
(sstatus pagepause) for a description of this flag.
(status features) returns a list of symbols representing the
features implemented in the LISP being used. The following
symbols may appear in this list:
(status uuolinks) returns a number which represents the number of
available slots for linking between compiled functions.
bibop pdp-10 big-bag-of-pages memory
management scheme
lap this LISP has a Lisp Assembly
Program
sort the sorting functions described in
chapter 9 are present
edit the edit function described in
chapter 17 is present
fasload the fasload facility described in
chapter 13 is necessary
↑f the "moby I/O" facility is present
bignum the arbitrary-precision arithmetic
package is included in this LISP
strings character strings and the functions
on them described in chapter 8 are
present
newio the I/O functions described in
chapter 12 are included in this
LISP; if this feature is not
present only some of those
functions are available.
ml this LISP is on the Nathlab machine
at MIT
ai this LISP is on the AI machine at
MIT
H6180 this LISP is on the H6180 Multics
machine at MIT
its this LISP is on some ITS system
Page 116 12.7 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
Multics this LISP is on some Multics system
dec10 this LISP is on some DEC TOPS-10
system; or on some TENEX system
since the TENEX implementation runs
under a TOPS-10 emulator.
(car (last (status features))) is generally considered to be an
implementation name, such as its or dec10 or Multics. The main
idea behind this status call is that an application package can
be loaded into any MACLISP implementation and can decide what to
do on the basis of the features it finds available.
Example:
(cond ((memq 'bignum (status features))
(prog2 nil (eval (read)) (read))) ;use first version
(t (read) (eval (read)) )) ;use second version
(defun factorial (n) ;bignum version
(cond ((zerop n) 1)
((times n (factorial (sub1 n))))
))
(defun factorial (n) ;fixnum-only version
(do () ((not (> n 13.))) ;do until n < 13.
(error "argument too big - factorial"
n
'wrng-type-arg))
(cond ((zerop n) 1)
((* n (factorial (1- n)))) ))
sstatus FSUBR
Sstatus is like status. It has a first argument which tells it
what to do and how to interpret the rest of its arguments.
Sstatus is used to set various system variables. The following
"sstatus functions" exist:
SSTATUS FUNCTIONS FOR THE I/O SYSTEM
(sstatus ioc ccc) is the same as (ioc ccc)
(sstatus uread --args--) is the same as (uread --args--)
(sstatus uwrite --args--) is the same as (uwrite --args--)
(sstatus crunit --args--) is the same as (crunit --args--)
11/18/73 12.7 Page 117
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
(sstatus charmode x f) sets the character-mode switch of the file
f (f may be nil to signify the terminal) to x, which may be t or
nil. x and f are evaluated. f may be omitted, in which case the
terminal is assumed.
SSTATUS FUNCTIONS FOR THE READER
See sections 12.1.2 and 12.6.2 for a description of how the
switches and tables set by these functions are used.
(sstatus chtran c k) sets c's character translation to k. k
follows the same rules as c, i.e. it may be a list which
evaluates to a fixnum, or an unevaluated atom such as a fixnum or
a character object. The value returned is k as a fixnum ascii
code.
(sstatus syntax c m) sets c's syntax bits to m. m is evaluated
and returned.
Note that in the above 3 calls, if c is a macro character it is
changed back to its standard syntax and chtran before the
requested operation is performed. However, if in the standard
readtable c is a macro (i.e. ' and ;), instead of being changed
to its standard syntax and chtran its syntax is set to 502
(extended alphabetic) and its chtran is set to itself.
(sstatus macro c f) makes c a macro character which calls the
function f with no arguments. f is evaluated. A fourth argument
to sstatus may be supplied. It is not evaluated. If it is an
atomic symbol whose pname begins with s, c is made a splicing
macro. If f is nil, instead of c being made a macro-character,
c's macro abilities are taken away and c becomes an ordinary
extended-alphabetic character.
(sstatus + x) sets the + switch to t or nil depending on x, which
is evaluated. The new value of the + switch is returned.
(sstatus ttyread x) sets the ttyread switch to t or nil depending
on x, which is evaluated. The new value of the switch is
returned.
SSTATUS FUNCTIONS FOR THE PRINTER
(sstatus terpri x) sets the terpri switch.
(sstatus abbreviate <n>) sets the abbreviation control to n.
(sstatus abbreviate nil) turns off abbreviation. (sstatus
abbreviate t) turns on a maximal amount of abbreviation. See
section 13.7 for a description of the abbreviation control.
Page 118 12.7 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
SSTATUS FUNCTION FOR THE GARBAGE COLLECTOR
(sstatus gctime n) resets the gctime counter to n and returns the
previous value of the gctime counter.
MISCELLANEOUS SSTATUS FUNCTIONS
(sstatus toplevel x) evaluates and returns x and sets the top
level form to this value.
(sstatus uuolinks) causes all links between compiled functions to
be "unsnapped." This should be done whenever (nouuo t) is done
to insure that the interpreter always gets a chance to save
debugging information on every function call.
(sstatus interrupt n f) sets the service function for user
interrupt channel n to f. The arguments are evaluated. F is
returned.
(sstatus pagepause x) sets the pagepause switch to x, which may
evaluate to t or nil. If the pagepause switch is t, and a
display terminal is being used, LISP will stop when it gets to
the end of the screen and wait for the user to hit control-U
before it erases anything. (This feature is not presently
available in the Multics implementation.)
*rset SWITCH
The value of *rset is the "*rset flag" manipulated by the status
and sstatus functions. If *rset is t, the interpreter keeps
extra information and makes extra checks to aid in debugging.
*rset should never be setq'ed - always use (sstatus *rset t) or
(sstatus *rset nil).
11/18/73 12.7 Page 119
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
12.8 Miscellaneous Functions
sysp SUBR 1 arg
The sysp predicate takes an atomic symbol as an argument. If the
atomic symbol is the name of a system function (and has not been
redefined), sysp returns the type of function (subr, lsubr, or
fsubr). Otherwise sysp returns nil.
Examples:
(sysp 'foo) => nil
(sysp 'car) => subr
(sysp 'cond) => fsubr
Page 120 12.8 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
12.8.1 Time
runtime SUBR no args
(runtime) returns the number of microseconds of cpu time used so
far by the process in which LISP is running. The difference
between two values of (runtime) indicates the amount of
computation that was done between the two calls to runtime.
time SUBR no args
(time) returns the time that the system has been up, in seconds.
(As a flonum.)
sleep SUBR 1 arg
(sleep n) causes a real-time delay of n seconds, then returns n.
n may be a fixnum or a flonum.
See also the alarmclock function, section 11.4.3.
11/18/73 12.8.1 Page 121
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
12.8.2 Getting into LISP
in the Multics implementation
The LISP subsystem is entered by means of the lisp command.
If lisp is called with no arguments, a copy of the standard
initial environment containing all the system functions and
variables is made the current environment. If the lisp command
is issued with an argument, the argument concatenated with
".sv.lisp" is the pathname of a saved environment (see the save
function in section 11.8.3.1) which is copied into the current
environment. Additional arguments to the lisp command in this
case are actually arguments to the programs in the saved
environment, which can retrieve them by using the function
'status'.
The LISP subsystem may also be entered through the
lispcompiler command, which is like calling lisp with an
argument of the pathname of the saved environment containing the
LISP compiler.
When the standard initial environment is entered, lisp checks
for a segment named startup.lisp in the user's home directory.
If such a segment exists, it is read in. Each form in the
segment is evaluated, but the value is not printed. This
facility allows users to "customize" LISP.
When a saved environment is entered, (mapc 'eval errlist) is
done. This feature can be used to make the saved environment
self-starting.
"...in the pdp-10 implementation"
in the ITS implementation
LISP may be entered by the ":LISP" or "LISP↑|K" command. The
environment set up by this command is the standard initial
environment. Lisp checks for a file named .LISP. (INIT) in the
user's directory. If it is found, it is read in and each form is
evaluated. This allows a user to "customize" lisp. The .LISP.
(INIT) file may begin with a comment in the form
(comment name number name number ...)
Page 122 12.8.2.1 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
which is used to specify allocation. The names are the names of
the various spaces, and the numbers are the sizes to be
allocated. If there is no .LISP. (INIT) file, lisp asks the
question ALLOC? A reply of n causes standard allocation, a reply
of y allows allocation to be specified conversationally. NB: it
is expected that the need for allocation will go away soon.
LISP may be entered by the command :LISP name1 name2 dev dir
where dev and dir default to DSK and the user's directory. In
this case the file dev:dir;name1 name2 is read in the same way as
a .LISP. (INIT) file.
If a lisp containing some data other than the initial
environment has been saved (see section 11.8.3.2) as TS NAME, the
:NAME command will retrieve it. The first action performed by
lisp is (mapc 'eval errlist), which allows the user programs to
start up.
in the DEC-10 implementation
Type the monitor command, R LISP. LISP will ask the question
"ALLOC?", and the possible answers are as described above for the
ITS implementation of LISP. Similarly to the ITS implementation,
if a lisp has been saved as NAME, the RUN NAME command will
retrieve it and the first thing it will do when retrieved is
(mapc 'eval errlist).
11/18/73 12.8.2.1 Page 123
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
12.8.3 Getting Out of LISP
Evaluating (ioc z) will cause LISP to temporarily release
control. Control can be returned to LISP by an implementation
defined method. There is also an implementation-defined way to
leave LISP permanently, freeing any storage used by the current
LISP environment or else saving it.
in the Multics implementation
(ioc z) will cause a QUIT. The start command may be used to
re-enter the lisp subsystem. release may also be used, in which
case LISP will clean itself up.
There are also the functions quit and save. quit causes the
lisp subsystem to exit, throwing away the current environment.
save causes the lisp subsystem to exit, saving the current
environment in a specified file, whose name always ends in
".sv.lisp".
quit SUBR no args
(quit) causes the lisp subsystem to remove itself and return to
its caller. The current environment is lost. (cf. save).
save FSUBR
(save foo) saves the current LISP environment in a file named
foo.sv.lisp in the working directory. Foo is not evaluated. The
command
lisp foo
can be used to retrieve this saved environment. All variable
bindings, file objects, array contents, and function definitions
(and other properties) are saved, but the contents of the push
down lists cannot be saved, so save should only be used from top
level.
Page 124 12.8.3 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
See also the function cline (described in section 11.8.4.1),
which is used to get out of LISP, execute one Multics command
line, and return into LISP.
in the ITS implementation
(ioc z) will cause a return to DDT. $P may be used to
re-enter LISP. (valret ':KILL) will cause LISP to exit, throwing
away the current environment. The macdmp function, explained
below, may be used to save the current environment.
macdmp LSUBR 0 or 1 args
If LISP is a top-level procedure, macdmp simply logs out.
Otherwise it prepares the LISP for dumping as follows:
(1) if the display slave is open, it is closed.
(2) all bit tables, pdl areas, and free storage lists are zeroed
out. (Remember, dumping with $Y uses a special compression
technique on blocks of zeros.)
(3) if macdmp was given an argument, this is explodec'ed and
valret'ed as with the valret function. Otherwise, macdmp
returns to DDT with a .BREAK 16,100000.
Commonly one will write a setup routine for some LISP package
like this: (prog ( ... )
(terpri)
(princ 'options:)
... read in options ...
(terpri)
(princ 'loading)
... load in files of functions ...
(macdmp ':$ALL/ DONE/ -/ hooray!$/↑M))
The LISP (with some new functions loaded) is now ready for
dumping. Alternatively, one might write
(macdmp '$Y/ USER/;FOO/ BAR/↑M:$ALL/ DONE$/↑M)
which will do the dump and then print a message when done.
When such a dumped LISP is loaded and restarted, the effect is
very similar to a ↑G quit: LISP's top level is entered after
evaluating all items on the errlist. Thus if before the macdmp is
done the errlist is setq'ed to some list of initialization
procedures, these procedures will be invoked when the dumped LISP
is restarted.
11/18/73 12.8.3 Page 125
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
in the DEC-10 implementation
********** TO BE SUPPLIED *********
Page 126 12.8.3 11/18/73
Functions for Controlling the Interpreter
***** ROUGH DRAFT #9905 *****
12.8.4 Sending Commands to the Operating System
in the Multics implementation
cline SUBR 1 arg
(cline x), where x is a character string, executes the Multics
command x and returns nil.
Example:
(cline "who -long")
in the ITS implementation
valret LSUBR 0 or 1 args
(valret) is like (ioc z); that is, it does a .LOGOUT if LISP is a
top level procedure, and otherwise valrets ":VK " to DDT.
(valret x) effectively performs an explodec on x (in practice x
is some strange atomic symbol like :PROCED/ :DISOWN/ ; but it
may be any s-expression). If the string of characters is one of
"$↑X.", ":KILL ", or ":KILL↑M" (the letters of KILL must be
capitalized) then valret performs a "silent kill" by executing a
.BREAK 16,20000; otherwise valret performs a .VALUE, giving the
character string to DDT to evaluate as commands.
Examples:
(valret ':PROCED/ :DISOWN/ )
procedes and disowns the LISP.
(valret '/ :KILL/ :TECO/↑M)
kills the LISP and starts up a TECO.
(valret '0$N)
causes DDT to print out the contents of all non-zero locations in
LISP.
11/18/73 12.8.4 Page 127
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
in the DEC-10 implementation
There is currently no way to do this in the DEC-10
implementation.
Page 128 12.8.4 11/18/73
Input and Output
***** ROUGH DRAFT #9905 *****
13. Input and Output
13.1 Basic I/O
Input and output can be done in LISP in terms of S-expressions or
in terms of characters. Operations may also be performed on certain
devices, such as displays, robot arms, etc., in terms which are
peculiar to the particular device, using the so-called "moby I/O"
facility.
Initially we will discuss just I/O on the user's terminal.
S-expressions can be input by using the function read. (read)
reads one S-expression, which is either a list enclosed in matching
parentheses or an atom delimited by a special character such as a
space or a parenthesis. (A parenthesis would be saved up and used on
the next call to read.) Read returns the S-expression which it read,
converting it from the external representation as characters to LISP
internal form. See Chapter 2 and section 13.1.2.
(readch) reads in one character and returns it as a character
object.
(tyi) reads in one character and returns a number which is the
ascii code for the character.
(print x) prints out the S-expression x in a form which is readable
by humans but which could also be read back into LISP if it was
printed to a file rather than to the terminal. See section 13.2.3 for
an explanation of how to do this.
The expression printed out is preceded by a newline and followed by
a space. If special characters are used with other than their normal
meanings, for example if a parenthesis appears in the pname of an
atom, they are preceded by slashes so that the output could be read
back in. Strings are enclosed in double quotes for the same reason.
(prin1 x) is the same as (print x) except that the leading newline
and trailing space are omitted. Prin1 can be used to print multiple
items on a line, but spacing between the items must be provided for
explicitly, for example by evaluating (tyo 40).
(princ x) is like (prin1 x) except that special characters are not
slashified and strings are not quoted. This makes the output more
11/18/73 13.1 Page 129
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
pleasing in certain situations, however it cannot be read back into
LISP.
(terpri) types out a newline.
Output of characters can be accomplished using either tyo or princ.
(tyo n) outputs a character whose ascii code is given by the number n.
princ may be used to output character objects.
As implied above, these functions can also be used to do I/O on
devices other than the terminal. The ways to do this will be
explained in section 13.2.3.
Note that what LISP does when it is at its "top level," that is
when you first start talking to it, is first to call read, then to
call eval on what was read, then to print the result and advance the
terminal to a new line on which the next piece of input may be typed.
This may be expressed as repeated evaluation of:
(prog2 (terpri)
(print (eval (read))) )
Page 130 13.1 11/18/73
Input and Output
***** ROUGH DRAFT #9905 *****
13.2 Files
I/O in LISP consists of communication between the LISP environment
and sequences of characters called files, located in the external
world. LISP refers to these files by using "file objects," which are
special objects within the LISP environment which serve as
representatives of, or symbols for, the files in the external world.
Because there is a one-to-one correspondence between files and file
objects, it is often convenient to confuse the two and call them both
"file."
The LISP system includes functions which can manipulate files in
various ways: A file may be "opened," that is a file object may be
created and associated with a named file in the external world.
A file may be "closed," that is the association between the
file-object and the external file may be broken and the file-object
deleted.
The file-accessing information contained in a file-object may be
examined or changed; for example, the line length of an output file
may be adjusted.
The characters of information in the external file may be read or
written.
The attributes of the external file, such as its name, may be
changed.
In order to "open" a file, the external file and the file object
must be named so that a connection may be established between them.
The problem of naming file objects is solved trivially by making the
rule that whenever a file object is created its name is decided by the
system and returned as the value of the function that created it.
File objects are then referred to in the same way as any S-expression.
Note that the name of a file object does not have a printable form, so
that if you want to manipulate the file object by typing from the
terminal (rather than from a program), you must keep the file object
as the value of an atomic symbol.
The naming of files in the outside world is more difficult because
MACLISP has to operate with several different outside worlds, that is,
under several different operating systems. It was thought undesirable
to build too many assumptions about the operating system into the
language, because that would restrict the transporting of programs
between MACLISP implementations.
The assumptions that are built in are that the operating system
provides named files located in named directories or on named devices,
which may be accessed sequentially as streams of characters. The
function filepos makes the additional assumption that simple
11/18/73 13.2 Page 131
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
random-access facilities are available. An interactive environment is
also assumed. Some of the I/O functions assume that the names of
files may be broken up into an arbitrary number of components, so that
names take on a form such as "foo.bar.lisp" or "moby mess". However,
it is possible for a MACLISP to operate with somewhat reduced
effectiveness under an operating system which does not satisfy all of
these assumptions.
The user of a program or a subsystem written in LISP wants to be
able to type in file names in the form customary in the particular
operating system being used, and he wants to see them typed out in the
same form. But if a program wants to do more with the file name
supplied by the user than simply pass it on to the system I/O
functions, it needs to have that name translated to a uniform internal
format, in which the interesting components of the name are seperate
atoms in a list, not buried inside a character string whose format is
not even known to the program. To resolve this conflict, two forms
for file names have been defined, and functions are provided to make
the implementation-dependent translation from one form to the other.
The forms of a file name are called the namelist and the namestring.
The namestring is the implementation dependent form. Namestrings
are represented as LISP character strings, however atomic symbols may
also be used, in which case the pname of the atomic symbol is used as
the character string. The contents of a namestring is just a sequence
of characters which have meaning to the user and to the function
"namelist," which converts a namestring to a namelist. Namestrings
should be read in using the "readstring" function and printed out
using "princ," so that no quotes will appear around them.
A namelist is a list whose car somehow specifies the device and/or
directory which contains the file, and whose cdr specifies the name of
the file. The exact way in which the car specifies the
device/directory is implementation-dependent. It should not be of
concern to programs. The cdr of a namelist is a list of names which
are the components of the file name if the operating system uses
multi-component file names. Each name is represented as an atomic
symbol, which is "interned" so that it may be tested with the function
eq.
An additional feature of namelists is the "star convention," by
which a namelist may contain unspecified components, which are
indicated by the atom *. Certain other constructions, explained in
section 13.3, may also be used. The star convention allows a single
namelist to specify a class of files, and allows programs to apply
defaults to their file-name arguments in a straightforward fashion.
Some additional information about file objects has been collected
here. It is in brief form and will be elaborated in later sections.
There is no way to input file objects to the reader, because they
do not have pnames or anything of that sort, but for convenience in
Page 132 13.2 11/18/73
Input and Output
***** ROUGH DRAFT #9905 *****
error messages and debugging the printer will print a file object as a
sharp sign (#), followed by the namestring of the external file to
which the file object is attached. # is the character which is used
to indicate that an object of unknown type is being printed.
The information contained within a file object is here described
briefly.
Namelist the namelist for the external file of which the
file object is a representative.
Eoffn a function which is applied when the end of an
input file is reached.
Endpagefn a function which is applied when the end of a page is
reached (on an output file.)
Linel the number of characters per line on an output
file.
Charpos the horizontal position on the line, where 0 is the left
margin.
Chrct the number of character positions remaining on the
current line of an output file,
Pagel the number of lines per page.
Linenum the number of the current line, with 0 being the top of the
page
Pagenum the number of the current page, with the first page being 0.
Filepos the position within the file of the character
currently being accessed. (Not necessarily
meaningful for all kinds of files.)
Other internal information used by the LISP I/O
functions in transactions with the operating
system.
Note that as a special case nil is considered to be a file object
which represents the terminal. This is in addition to nil's other
identities as an atomic symbol and as a list.
.in +%undent%
11/18/73 13.2 Page 133
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
13.2.1 Naming Files
Some examples may help clarify the connection between namelists and
namestrings.
In the Multics system, files are stored in a tree structure of
directories. A file's name consists of a sequence of names seperated
by the ">" character. The last name is the name of the file, and
preceding names are the names of directories in a path from the "root"
directory down through the tree to the file in question. Each name
may consist of several compoenents seperated by periods. Thus a
typical namestring in the Multics implementation of MACLISP would be
">udd>AutoProg>Hacker>hacks>my.new.hack"
The corresponding namelist is:
(>udd>AutoProg>Hacker>hacks my new hack)
In addition, the start convention for namelists may also be
represented in namestring form. Some examples of the correspondence
are:
(* foo) == "foo" - omitted components are *
(* foo * bar) == "foo.*.bar"
(* foo . bar) == "foo.**.bar"
(*foo . *) == "foo.**"
Multics LISP can also use "streams" for files. Streams are a
sequential-I/O entity in Multics. For example, input from and output
to the terminal are performed by means of streams. In LISP the
convention has been defined that a "$" character in a namestring
distinguishes the name of a stream from the name of a file stored in
the directory hierarchy. Thus the namestring
"$userinput"
indicates the stream used for input from the terminal. The
corresponding namelist is:
(stream userinput)
In the ITS (pdp-10) system, files are stored in directories which
are kept on devices. Directories may not be kept within directories,
so there is no tree structure. Each file-name has exactly two
components. Thus a file whose name has first component foo and second
component bar, located in directory comlap on device ml, would have
the namestring:
ml:comlap;foo bar
As a namelist this would be represented:
Page 134 13.2.1 11/18/73
Input and Output
***** ROUGH DRAFT #9905 *****
((ml . comlap) foo bar)
If the device and directory were omitted, the namelist would be:
(* foo bar)
If only one component to the name were specified, the second would be
*.
In the DEC-10 implementation, namestrings take the usual
dev:name.ext[proj,prog]
form, and the corresponding namelist is
((dev proj prog) name ext)
and *'s are substituted for omitted components in the same way as for
the ITS version described above.
namelist SUBR 1 arg
Namelist converts its argument to a namelist. Omitted or *
components in the argument produce *'s in the result.
namestring SUBR 1 arg
Namestring converts its argument from a namelist to a namestring.
It is the opposite of namelist.
shortnamestring SUBR 1 arg
shortnamestring is just like namestring except that there is no
mention of directory or device in the resulting string. Example:
(shortnamestring '(abc d e)) => "d.e"
11/18/73 13.2.1 Page 135
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
names LSUBR 1 or 2 args
(names f), where f is a file object, gets f's namelist.
(names nil) gets the default namelist. In Multics MACLISP, the
default namelist is initially set to
(<working-directory> . *)
when lisp is entered.
In ITS MACLISP, the default namelist is initially set to
(<udir> . *)
when lisp is entered, where <udir> is the name by which the user
logged in.
(names nil x) sets the default namelist to x and returns x.
13.2.2 Opening and Closing
openi SUBR 1 arg
This function is used to create a file object and associate it
with a file in the external world. The argument is a namelist or
namestring which specifies the file to be opened. The return
value is the file object which was created.
Openi first creates a file object and initializes its namelist,
linel, and eoffn to the defaults. Its chrct is initialized equal
to its linel. Then the namelist argument of openi is merged into
the namelist of the file object. See the description of the
mergef function, in section 13.3, for the full details.
Basically what happens is that components of the file name not
specified by the argument to openi are obtained from the default
namelist. openi now negotiates with the operating system to
obtain the file. A fail-act correctable error occurs if this
does not succeed.
The file created by openi can be used for input.
Example:
(inpush (openi "inputfile1"))
Page 136 13.2.2 11/18/73
Input and Output
***** ROUGH DRAFT #9905 *****
openo SUBR 1 arg
Openo is like openi except that the file object created is used
for output. Any pre-existing file of the same name is
over-written. Example:
(setq outfiles (list (openo "output.data")))
The following function only exists in the Multics implementation, at
present.
opena SUBR 1 arg
Opena is just like openo except that if there is a pre-existing
file with the same name, the output is appended to the end of the
file, where openo would erase the old contents of the file and
begin outputting at the beginning of the file.
close SUBR 1 arg
(close x), where x is a file, closes x and returns t. If x is
already closed nothing happens, otherwise the file system is
directed to return x to a quiescent state.
For a description of the way in which the argument to openi, openo, or
opena has the defaults applied to it, see section 13.3.
13.2.3 Specifying the Source or Destination for I/O
When an I/O function is called, the source (file) from which it is
to take its input or the destinations (files) on which it is to put
its output may be specified directly as an argument to the function,
or they may be specified by default. The default input source and
output destinations are specified by several system variables, which
may be setq'ed or lambda-bound by the user. They are described below.
infile is the default input source, if the switch ↑q is t. If ↑q
is nil the terminal is used as the default input source.
outfiles is a list of default output destinations. Output is sent
to all of these files if the ↑r switch is t. Output also goes to the
terminal unless the ↑w switch is t.
Note that in the values of infile and outfiles nil means the
terminal, any anything other than nil must be a file object.
11/18/73 13.2.3 Page 137
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
infile VARIABLE
The value of infile is a file object which is the default input
source if ↑q is non-nil. Infile can also be nil which specifies
that input will be from the terminal even if ↑q is not nil. The
initial value of infile is nil.
↑q SWITCH
If the value of ↑q is non-nil, the default input source is the
value of the atom infile. If ↑q is nil, the default input source
is nil, i.e. the terminal.
instack VARIABLE
The value of instack is a list of pushed-down values of infile.
It is managed by the function inpush. The initial value is nil.
outfiles VARIABLE
The value of outfiles is a list of file objects which are output
destinations if ↑r is not nil. Elements of the list outfiles may
be either file objects created by openo or opena, or nil meaning
output to the terminal. Note that output goes to the terminal
anyway if ↑w is nil, so it is possible to get double characters
this way.
↑r SWITCH
If the value of ↑r is non-nil, the default output destinations
include the files in the list which is the value of the atom
outfiles.
↑w SWITCH
If the value of ↑w is non-nil, the default output destinations do
not include the terminal. (Unless ↑r is on and nil is a member
of the outfiles list.)
Page 138 13.2.3 11/18/73
Input and Output
***** ROUGH DRAFT #9905 *****
Now the basic I/O functions can be explained in full detail:
read LSUBR 0 to 2 args
This is the S-expression input function.
(read) reads an S-expression from the default input source.
(read f), where f is a file or nil meaning the terminal, reads an
S-expression from f. During the reading, infile and ↑q are bound
so that evaluation of (read) within a macro-character function
will read from the correct input source.
(read x), where x is not a file and not nil, passes x as an
argument to the end-of-file function of the input source if the
end of the file is reached. Usually this means that read will
return x if there are no more S-expressions in the file.
(read t) suppresses the calling of the end-of-file function if
the end of the file is reached. Instead, read just returns t.
(read x f) or (read f x) specifies the end-of-file value x and
selects the input source f.
readch LSUBR 0 to 2 args
Readch reads in one character and returns a character object.
The arguments are the same as for read.
readline LSUBR 0 to 2 args
readline reads in a line of text, strips off the newline
character or characters at the end, and returns it in the form of
a character string. The arguments are the same as for read. The
main use for readline is reading in file names typed by the user
at his terminal in response to a question.
tyi LSUBR 0 to 2 args
Tyi inputs one character and returns a fixnum which is the ascii
code for that character. The arguments are the same as for read.
11/18/73 13.2.3 Page 139
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
tyipeek LSUBR 0 or 1 arg
(tyipeek) is like (tyi) except that the character is not eaten;
it is still in the input stream where the next call to an input
function will find it. Thus (= (tyipeek) (tyi)) is t. If the
end of the file is reached, tyipeek returns 3, (the ascii code
for "end of text.") The end of file function is not called.
(tyipeek n), where n is a fixnum < 200 octal, skips over
characters of input until one is reached with an ascii code of n.
That character is not eaten.
(tyipeek n), where n is a fixnum > 1000 octal, skips over
characters of input until one is reached whose syntax bits from
the readtable, logically anded with (lsh n -9.), are nonzero.
(tyipeek t) skips over characters of input until the beginning of
an S-expression is reached. Splicing macro characters, such as
";" comments, are not considered to begin an object. If one is
encountered, its associated function is called as usual (so that
the text of the comment can be gobbled up or whatever) and
tyipeek continues scanning characters.
prin1 LSUBR 1 or 2 args
(prin1 x) outputs x to the current output destination(s), in a
form suitable for reading back in.
(prin1 x f) outputs x on the file f, or the terminal if f is
nil.
print LSUBR 1 or 2 args
Print is like prin1 except that the output is preceded by a
newline and followed by a space. This is the output function
most often used.
(print x) prints x to the default output destinations.
(print x f) prints x to the file f, or to the terminal if f is
nil.
Page 140 13.2.3 11/18/73
Input and Output
***** ROUGH DRAFT #9905 *****
princ LSUBR 1 or 2 args
Princ is like prin1 except that special characters are not
slashified and strings are not quoted.
(princ x) outputs x to the current output destination(s).
(princ x f) outputs x to the file f, or the terminal if f is nil.
tyo LSUBR 1 or 2 args
(tyo n) types out the character whose ascii code is n on the
current output destination(s).
(tyo n f) types out the character whoe ascii code is n on the
file f or on the terminal if f is nil. Tyo returns its first
argument.
terpri LSUBR 0 or 1 arg
(terpri) sends a newline to the current output destination(s).
(terpri x) sends a newline to x, where x may be an output file or
nil meaning the terminal.
inpush SUBR 1 arg
(inpush x), where x is a file object open for input or nil to
specify the terminal, pushes the current input source onto the
input stack and selects x as the current input source. This is
like
(setq instack (cons infile instack))
(setq infile x)
x is returned.
(inpush 0) just returns infile.
(inpush -1) pops a new input source off of the input stack:
(setq infile (car instack)
instack (cdr instack))
The above code is wrong in the case where instack is nil, i.e.
empty. In this case inpush leaves instack nil and makes infile
11/18/73 13.2.3 Page 141
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
nil, which means the terminal.
(inpush -n) does (inpush -1) n times.
(inpush 1) does (inpush (inpush 0)), (inpush +n) does that n
times.
The value of inpush is the newly selected input source. If
inpush causes infile to be set to nil, ↑q is set to nil since the
terminal has become the input source.
13.2.4 Handling End of File
Calls to the input functions read, readch, readstring, and tyi
specify an argument called the "eofval." If this argument is omitted
nil is assumed. If the end of the input file is reached during the
execution of the function, the eofval argument is used by the
following procedure:
Each file object has an end-of-file handler, its eoffn. When an
end of file occurs while input is being taken from this file, the
eoffn is examined. (Eof on the terminal cannot occur.) If the eoffn
is nil, then the following default action is taken: If eofval on the
call to read was not supplied, then the input file is closed and read
continues taking characters from a new input file popped off the input
stack. If the input stack is empty, (setq ↑q nil) is done and read
continues reading from the terminal. If an eofval was supplied on the
call to read, then read immediately returns it. The input file is not
closed.
This is not strictly true in the case where the input function is
read or readstring and it is in the middle of an object. In this
case, rather than allowing the object to cross files, a fail-act error
occurs. The argument passed to the user interrupt service function is
the list (read-eof). If the interrupt service function returns an
atom (such as nil), read errs out; but if it returns a list, read
goes on reading from the new input source as if there had not been any
end-of-file.
If the eoffn for the input file is not nil, then it is a function
and it is applied with two arguments. The first argument is the file
object that eof'ed. The second argument is the eofval on the call to
read, or, if an eofval was not supplied, nil. If the eoffn returns
nil, the file is closed and reading continues from the input source
popped off the input stack. The above prohibition of objects crossing
eofs applies. If the eoffn returns t, reading continues from whatever
input source was made the current default one by the eoffn. If the
eoffn returns something other than t or nil, then read immediately
Page 142 13.2.4 11/18/73
Input and Output
***** ROUGH DRAFT #9905 *****
returns whatever the eoffn returned, and the file is not closed unless
the eoffn closes it.
eoffn LSUBR 1 or 2 args
(eoffn x), where x is an input file, gets x's end-of-file
function. The end-of-file function is called if the end of the
file is reached during input.
(eoffn nil) gets the default end-of-file function.
(eoffn x f) sets x's end-of-file function to f.
(eoffn nil f) sets the default end-of-file function to f.
f may be nil, which means that no end-of-file function is to be
used.
11/18/73 13.2.4 Page 143
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
13.3 Applying Defaults to File Names
The I/O system provides a mechanism for applying defaults which
programs can use and which is used when a file object is created by
the open functions.
A default namelist, linel, and eoffn are remembered for
initializations of file objects. Output to the terminal uses the
default linel. These defaults may be examined or modified by using
the names, linel, or eoffn function with a first argument of nil. The
chrct for output to the terminal may be examined or modified by using
the chrct function with a first argument of nil. When a file object
is created, its linel and eoffn are set to the defaults.
There is also a system of defaults for file names (actually for
namelists), which is based on the use of namelists containing the
special atom *.
If one of the elements in a namelist is the atom *, it indicates
that that component is not specified. Thus the namelist
(* foo bar)
specifies a file named foo.bar but it is not said in what directory or
on what device it exists. Similarly a namelist like
(dir foo *)
indicates a file in directory dir, with a two component name of which
the first component is foo, but the second component is not specified.
A namelist may also be dotted, that is, it may end with an atom
rather than with nil. If it ends with an atom other than *, i.e. if
it looks like
(devdir name1 name2 name3 . foo)
it specifies a file whose name begins with the components
name1.name2.name3, ends with the component foo, and may also have any
number of components in between. For example, ignoring directories,
in a system such as Multics where the namestring consists of the
file-name components from the namelist concatenated together with
periods, the namelist
(-- moe larry . mung)
could specify all of the following file names:
moe.larry.mung
moe.larry.curly.mung
moe.larry.foo.bar.blech.mung
Page 144 13.3 11/18/73
Input and Output
***** ROUGH DRAFT #9905 *****
and so on. This form of namelist can be used to apply what is
sometimes called a "default extension."
A namelist can also have a dotted star, that is it can be in the
form
(devdir -names- . *)
This specifies a file whose name begins with the components -names-,
and may have zero or more components following those. Thus
(-- mung bung . *)
means any of these file names:
mung.bung
mung.bung.lung
mung.bung.foo.goo.zoo
The process of applying defaults to file names consists of
"merging" two (or more) namelists into a single namelist, where one of
the namelists is a user-supplied file specifier and the other is a set
of defaults. For this purpose, the function mergef is supplied.
Mergef is also used by openi and openo when they combine their
argument with the default namelist to get the namelist of the file
being opened.
mergef LSUBR 2 or more args
Mergef is used for applying defaults to file specifiers, which
may be namelists or namestrings.
(mergef x y) returns a namelist obtained by selecting components
from x and y, which are converted to namelists. Where a
component of x is *, the corresponding component of y is
selected. It is an error if y is not that long. When a
component of x is not *, it is selected and the corresponding
component of y is skipped. If y ends with a dotted atom other
than a * this atom is added to the end of the namelist if its not
already there. The same applies if x ends with a dotted atom.
If x ends with a dotted *, the rest of y is copied over.
(mergef x nil) strips off the last component of x.
(mergef w x y z)
is equivalent to
(mergef (mergef (mergef w x) y) z).
11/18/73 13.3 Page 145
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
13.4 Requests to the Operating System
13.4.1 Manipulating the Terminal
tty VARIABLE
The value of the atom tty is initially set to a number describing
the type of terminal being used. The values presently defined
are:
0 normal terminal with no special capabilities
1,2 various display terminals
3 Imlac terminal.
cursorpos LSUBR 0 or 2 args
The cursorpos function is used to manipulate the cursor on a
display terminal.
With no arguments it returns the dotted pair (line . column),
where line is the line number, starting from 0 at the top of the
screen, and column is the column position, starting from 0 at the
left edge of the screen. If the terminal being used is not a
display terminal with this type of cursor, nil is returned
instead.
With two arguments, (cursorpos line column) moves the display
cursor to the indicated position and returns t if it was
successful, or nil if the terminal was incapable of doing this.
listen SUBR no args
(listen) returns a fixnum which is non-zero if there is any input
that has been typed in on the terminal but has not yet been read.
13.4.2 File System Operations
Page 146 13.4.2 11/18/73
Input and Output
***** ROUGH DRAFT #9905 *****
deletef SUBR 1 arg
(deletef x), where x specifies a file, deletes that file. The
return value is the namelist of the file actually deleted, i.e.
x mergef'ed over the defaults. Example:
In the Multics implementation,
(deletef "foo.bar") => (>udd>ap>junk foo bar)
In the ITS implementation,
(deletef "foo bar") => ((ml loser) foo bar)
rename SUBR 2 args
(rename x y), where x and y are namelists or namestrings, renames
the file specified by (mergef x (names nil)) to the name
specified by (mergef y x (names nil)). The directory part of y
is ignored; a file may not be renamed onto a different device or
directory. The return value is the namelist of the new name of
the file.
Example:
In the Multics implementation,
(rename "foo.baz" "*.bar") => (>udd>Bar>Foo foo bar)
and renames >udd>Bar>Foo>foo.baz to foo.bar.
In the ITS implementation,
(rename "foo baz" "* bar") => ((ml loser) foo bar)
and renames ml:loser;foo baz to foo bar.
allfiles SUBR 1 arg
(allfiles x), where x is a namelist, returns a list of namelists
which are precise; i.e. they do not contain any stars or dotted
parts. These are the namelists for all the files in the file
system which match the namelist x. Whatever search rules are
customary in the particular operating system are used.
Allfiles with a precise namelist as an argument can be used as a
predicate to determine whether or not a file exists.
clear-input SUBR 1
(clear-input x), where x is a file or nil meaning the terminal,
causes any input that has been received from the device but has
not yet been read to be thrown away, if that makes sense for the
particular device involved.
11/18/73 13.4.2 Page 147
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
force-output SUBR 1
(force-output x), where x is a file or nil meaning the terminal,
causes any buffered output to be immediately sent to the device.
13.4.3 Random Access to Files
filepos LSUBR 1 or 2 args
(filepos x), where x is a file object open for input, returns the
current character position within the file as a fixnum. The
beginning of the file is 0.
(filepos x n), where x is a file object open for input and n is a
non-negative fixnum, resets the character position of the file to
position specified by n. It is an error if this position does
not lie within the file or if the file is not randomly
accessible. N is returned.
Page 148 13.4.3 11/18/73
Input and Output
***** ROUGH DRAFT #9905 *****
13.5 The Old "Uread" I/O System
The functions uread, uwrite, ufile, ukill, and crunit are part
of an older LISP I/O system. They are retained for
compatibility. Various "status" functions are also part of this
older I/O system. (See section 12.7)
These five functions name files in a different way from the
other I/O functions. A file is named by a 4-list,
(name1 name2 dev dir)
Name1 and name2 together make up the "filename," dev is the
"device," and dir is the "directory." In the ITS implementation
of MACLISP, these go together to make up the ITS file name:
DEV: DIR; NAME1 NAME2
In the DEC-10 implementation, dev is the device name, name1 is
the file name, name2 is the extension, and dir is a list of two
fixnums, the project number and the programmer number. Thus the
4-list
(name1 ext dev (proj prog))
represents the file
dev:name1.ext[proj,prog]
In the Multics implementation, dev is ignored and dir is the
directory pathname. The entry-name is name1.name2. Thus the
Multics filename is:
dir>name1.name2
These five functions maintain their own set of defaults, which
are updated every time one of these functions is called, so that
the defaults correspond to the last file that was used. The
defaults may be examined with (status crfile), which returns the
first two elements of the default 4-list, and (status crunit)
which returns the last two.
It is not necessary to specify all four parts of the 4-list
when one of these five functions is used. Any omitted parts are
taken from the defaults.
These functions are fsubrs which do not evaluate their
arguments. They may be applied to a 4-list, e.g.
(apply 'uread '(foo bar dsk comlap))
or they may be called with the 4-list as four arguments, which is
convenient when calling them from top level.
11/18/73 13.5 Page 149
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
uread FSUBR
This function selects an input file. The argument list is a
4-list as described above. The specified file is made the
default input source. Note that the ↑q switch mst be turned
onbefore input will be automatically taken from this file.
uwrite FSUBR
Uwrite opens an output file. When done with this file, ufile
must be used to close it and give it a name. The arguments are
the last two elements of a 4-list, specifying the device and
directory on which the file is to be written. The first two
parts of the 4-list are not specified until the file is ufile'd.
ufile FSUBR
(ufile name1 name2) closes the uwrite output file and gives it
the name name1.name2. (ufile) takes name1 and name2 from the
defaults.
crunit FSUBR
(crunit) gets the current device and directory.
(crunit dev dir) sets the device and directory and returns it.
The arguments are not evaluated. Example:
(crunit) => (dsk >udd>Bar>Foo>subdirectory)
ukill FSUBR
(ukill -args-), where -args- are like uread, deletes the
specified file.
uread VARIABLE
The value of uread is a file object being used for input
initiated by the uread function, or nil if no file is currently
being uread.
Page 150 13.5 11/18/73
Input and Output
***** ROUGH DRAFT #9905 *****
uwrite VARIABLE
The value of uwrite is a file object being used for output
initiated by the uwrite function, or nil if no file is currently
being uwritten.
There are also some status/sstatus functions associated with these.
These are (status crunit), (status crfile), (status uread), and
(status uwrite).
11/18/73 13.5 Page 151
LISP/MACLISP Reference Manual
***** ROUGH DRAFT #9905 *****
13.6 Advanced Use of the Reader
13.6.1 The Obarray
obarray VARIABLE & ARRAY
The value of obarray is an array which is a table of known atomic
symbols - when an atomic symbol is read in it is "interned" on
this obarray, that is made eq to any atomic symbols with the same
pname that were previously read in. If an atomic symbol, such as
one created by (gensym), is not in this table an atom read in
with the same pname will not be the same atom - there will be two
seperate copies.
The obarray may be manipulated by the functions remob and intern.
A new obarray may be created by using the makoblist function.
The atom obarray may be setq'ed or lambda-bound to different
obarrays at different times, which allows multiple sets of atomic
symbols to be kept seperate - you can have different atomic
symbols with the same pname interned on different obarrays at the
same time.
Note that the value of obarray is not an atomic symbol which
names an array, but the array itself, obtainable by (get name
'array).
The array property of obarray is the same array as its initial
value.
Example of the use of multiple obarrays:
(setq private-obarray
(get (makoblist 'private-obarray) 'array))
;make another obarray.
((lambda (obarray) (read)) private-obarray)
;read using atoms on private obarray
;instead of regular one
makoblist SUBR 1 arg
(makoblist nil) returns a list of lists of atoms which is a
representation of the current obarray.
(makoblist 'foo) gives the atom foo an array property of a copy
of the current obarray.
Page 152 13.6.1 11/18/73
Input and Output
***** ROUGH DRAFT #9905 *****
See also the functions remob (page 50) and intern (page 50.)
13.6.2 The Readtable
readtable VARIABLE & ARRAY
The value of readtable is an array which contains tables used by
the reader to determine the meaning of input characters. This
array may be manipulated using the functions status, sstatus, and
setsyntax. Multiple readtable-arrays may be constructed by using
the makreadtable function, and the atom readtable may be
lambda-bound or setq'ed to one or another of these readtables.
Note that the value of readtable∪β ***** ROUGH DRAFT #9905 *****
See also the functions remob (page 50) and intern (page 50.)
13.6.2 The Readtable
readtable VARIABLE & ARRAY
The value of readtable is an array which contains tables used by
the reader to determine the meaning of input characters. This
array may be manipulated using the functions status, sstatus, and
setsyntax. Multiple readtable-arrays may be constructed by using
the makreadtable function, and