5. Evaluation
The following is a complete description of the actions taken by the
evaluator, given a form to evaluate.
If form is a number, the result is form .
If form is a string, the result is form .
If form is a symbol, the result is the binding
of form . If form is unbound, an error is signalled.
If form is not any of the above types, and is not a list,
an error is signalled.
If form is a special form, indentified by a distinguished
symbol as its car, it is handled accordingly; each special form works
differently. All of them are documented in this manual.
If form is not a special form, it calls for the application
of a function to arguments . The car of the form is a function or
the name of a function. The cdr of the form is a list of forms which
are evaluated to produce arguments, which are fed to the function. Whatever
results the function returns is the value of the original form .
[Here there should be the rest of the moby description of evaluation and application,
particularly multiple values. Explain the term "variables", also a very
brief bit about locals and specials (fluids and lexicals??).
The nature of functions should be revealed;
including compiled-code, interpreted-code, arrays, stacks, closures,
symbols. Discuss macros.
Talk about function-calling in compiled code, how this is essentially
identical to the apply function, and no need for (sstatus uuolinks)
and the like.]
5.1 Functions and Special Forms
eval
x
(eval x) evaluates
x , and returns the result.
Example:
(setq x 43 foo 'bar)
(eval (list 'cons x 'foo))
=> (43 . bar)
It is unusual to explicitly call
eval , since usually
evaluation is done implicitly. If you are writing a simple Lisp program and
explicitly calling
eval , you are probably doing something wrong.
eval is primarily useful in programs which deal with Lisp itself,
rather than programs about knowledge or mathematics or games.
Also, if you are only interested in getting at the value of a
symbol (that is, the contents of the symbol's value cell), then you
should use the primitive function
symeval .
'findex "symeval"
Note: the actual name of the compiled code for
eval is "
si:*eval ";
this is because use of the
evalhook feature binds the function cell of
eval .
If you don't understand this, you can safely ignore it.
'findex "evalhook"
Note: unlike Maclisp, eval never takes a second argument; there
are no "binding context pointers" in Lisp Machine Lisp.
They are replaced by Closures (see LINK:(closure)).
apply
fn arglist
(apply fn arglist) applies the function
fn to the list of
arguments
arglist .
arglist should be a list;
fn can be a
compiled-code object, or a "lambda expression", i.e., a list whose
car
is the symbol
lambda , or a symbol, in which case its definition (the contents
of its function cell) is used.
Examples:
(setq f '+) (apply f '(1 2)) => 3
(setq f '-) (apply f '(1 2)) => -1
(apply 'cons '((+ 2 3) 4)) =>
((+ 2 3) . 4) not (5 . 4)
Of course,
arglist may be
nil .
Note: unlike Maclisp,
apply never takes a third argument; there
are no "binding context pointers" in Lisp Machine Lisp.
Compare
apply with
funcall and
eval .
funcall
f &rest args
(funcall f a1 a2 ... an) applies the function
f to the arguments
a1, a2, ..., an .
f may not
be a special form nor a macro; this would not be meaningful.
Example:
(cons 1 2) => (1 . 2)
(setq cons 'plus)
(funcall cons 1 2) => 3
lexpr-funcall
f &rest args
lexpr-funcall is like a cross between
apply and
funcall .
(lexpr-funcall f a1 a2 ... an list) applies the function
f
to the arguments
a1 through
an followed by the elements of
list .
Examples:
(lexpr-funcall 'plus 1 1 1 '(1 1 1)) => 6
(defun report-error (&rest args)
(lexpr-funcall (function format) error-output args))
Note: the Maclisp functions subrcall , lsubrcall , and arraycall
are not needed on the Lisp Machine; funcall is just as efficient.
'findex "subrcall"
'findex "lsubrcall"
'findex "arraycall"
quote Special Form
(quote x) simply returns x . It is useful because it takes the
argument quoted , so that it is not evaluated by eval . quote is used
to include constants in a form.
Examples:
(quote x) => x
(setq x (quote (some list))) x => (some list)
Since
quote is so useful but somewhat cumbersome to type, the reader normally
converts any form preceded by a single quote (
' ) character into a
quote form.
For example,
(setq x '(some list))
is converted by read into
(setq x (quote (some list)))
function Special Form(function x) is similar to quote , except that it implies
to the compiler that x is a function. In the interpreter, if x is a symbol
(function x) returns x 's definition;
otherwise x itself is returned.
Because of this, using function rules out the possibility of later
changing the function definition of x , including tracing it. Care is required!
@define Macro This macro turns into nil . It exists for the sake of the
@ listing generation program, which uses it to declare names of special forms
which define objects (such as functions) which @ should cross-reference.
progn Special FormA progn-form looks like
(progn form1 form2 ...) .
The
forms are evaluated in order from left to right and the value
of the last one is the result of the progn.
progn is the primitive control structure construct for "compound
statements". Although lambda-expressions, cond-forms, do-forms, and
many other control structure forms use
progn implicitly, that is,
they allow multiple forms in their bodies, there are occasions when
one needs to evaluate a number of forms for their side-effects and
make them appear to be a single form.
Example:
(foo (cdr a)
(progn (setq b (extract frob))
(car b))
(cadr b))
prog1 Special Formprog1 is similar to
progn , but it returns the value of its
first form.
It is most commonly used to evaluate an expression with side effects, and return
a value which must be computed
before the side effects happen.
Example:
(setq x (prog1 y (setq y x)))
which interchanges the values of the variables
x and
y .
prog1 could have been defined as:
(defun prog1 (&rest values)
(car values))
It is actually implemented as a macro which expands into a
prog2 .
prog2 Special Formprog2 is similar to progn and prog1 ,
but it returns its second argument.
It is included largely for Maclisp compatibility. It has two purposes: to evaluate
two forms sequentially, which can be done more generally with progn , or
to do what prog1 is used for (c.f. prog1 above).
let Special Formlet is used to bind some variables for some objects.
A
let form looks like
(let ((var1 vform1 )
(var2 vform2 )
...)
bform1
bform2
...)
When this form is evaluated, first the
vform s are evaluated.
Then the
var s are bound to the values returned by the
corresponding
vform s. Finally, the
bform s are evaluated sequentially
and the result of the last one returned.
let is implemented as a macro which expands into a lambda-combination;
however, it is preferable
to use
let rather than
lambda because the variables and the corresponding forms
appear textually close to each other, which increases readability
of the program.
See also let-globally , LINK:(let-globally-fun).
progv Special Formprogv is a special form to provide the user with extra control
over lambda-binding. It binds a list of symbols to a list of values,
and then evaluates some forms. The lists of symbols and values
are computed quantities; this is what makes
progv different from
lambda ,
let ,
prog , and
do .
(progv symbol-list value-list form1 form2 ... )
first evaluates
symbol-list and
value-list . Then the symbols
are bound to the values. In compiled code the symbols must be
special ,
since the compiler has no way of knowing what symbols might appear in the
symbol-list . If too few values are supplied, the remaining symbols
are bound to
nil . If too many values are supplied, the
excess values are ignored.
After the symbols have been bound to the values, the
form s are
evaluated, and finally the symbols' bindings are undone.
The result returned is the value of the last form. Note that the
"body" of a
progv is similar to that of
progn , not that of
prog .
Example:
(setq a 'foo b 'bar)
(progv (list a b 'b) (list b) (list a b foo bar))
=> (foo nil bar nil)
During the evaluation of the body of this
progv ,
foo
is bound to
bar ,
bar is bound to
nil ,
b is
bound to
nil , and
a remains bound to
foo .
See also bind (see LINK:(bind-fun)), which is a
subprimitive which gives you maximal control over binding.
The following three functions (arg , setarg , and listify )
exist only for compatibility with Maclisp lexprs .
arg
x
(arg nil) , when evaluated during the application of
a lexpr, gives the number of arguments supplied to that
lexpr.
This is primarily a debugging aid, since lexprs also receive their number of arguments
as the value of their
lambda -variable.
(arg i) , when evaluated during the application of 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 2)) ;print the second argument.
(+ (arg 1) ;return the sum of the first
(arg (- nargs 1)))) ;and next to last arguments.
setarg
i x
setarg is used only during the application of 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
n
(listify n) 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
argument
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)
(listify1 (arg nil) (+ (arg nil) n 1)))
(t
(listify1 n 1)) ))
(defun listify1 (n m) ; auxiliary function.
(do ((i n (1- i))
(result nil (cons (arg i) result)))
((< i m) result) ))
5.2 Functions and Special Forms
The Lisp machine includes a facility by which the evaluation of a form
can produce more than one value. When a function needs to return more
than one result to its caller, multiple values are a cleaner way of doing
this than returning a list of the values or setq 'ing special variables
to the extra values.
In the normal case, multiple values are not used. Special syntax is
required both to produce multiple values and to receive them.
If the caller does not receive multiple values, the first of the
multiple values will be received as the ordinary value.
The primitive for producing multiple values is return , which when
given more than one argument returns all its arguments as the values of
the prog or do from which it is returning. The variant
return-from also can produce multiple values. Many system functions
produce multiple values, but they all do it via the return primitive.
The special forms for receiving multiple values are multiple-value ,
multiple-value-list , and multiple-value-bind . These include
a form and an indication of where to put the values returned by that form.
multiple-value Special Form(multiple-value var-list form) is a special
form used for calling a function which
is expected to return more than one value.
var-list should be a list of variables.
form is evaluated, and the variables in var-list
will be set (not lambda-bound) to the values returned by form . If more values
are returned than there are variables in var-list , then the extra values
are ignored. If there are more variables than values returned,
extra values of nil are supplied. It is allowed to have nil
in the var-list , which means that the corresponding value is to be
ignored (you can't use nil as a variable.)
Example:
(multiple-value (symbol already-there-p)
(intern "goo"))
intern returns a second value, which is
t if the symbol returned as the
first value was already on the obarray, or else
nil if it just put it there.
So if the symbol
goo was already on the obarray, the variable
already-there-p
will be set to
t , else it will be set to
nil .
multiple-value is usually used for effect rather than for value, however
its value is defined to be the first of the values returned by
form .
multiple-value-bind Special FormThis is similar to
multiple-value , but locally binds the variables which
receive the values, rather than
setq ing them. The form looks like:
(multiple-value-bind (var1 var2... )
(function args... )
body... )
The scope of the binding of
var1 ,
var2 , etc. is
body ; they are
not bound until after the function call.
multiple-value-list Special Form(multiple-value-list form) evaluates
form , and returns a list of
the values it returned. This is useful for when you don't know how many values
to expect.
Example:
(setq a (multiple-value-list (intern "goo")))
a => (goo nil #<Package User>)
This is similar to the example of
multiple-value above;
a will be set
to a list of three elements, the three values returned by
intern .
The first is the newly interned symbol
goo , the second is
nil to indicate that it is newly-interned, and the third is
the package on which it was interned.
Due to the syntactic structure of Lisp, it is often the case that the value
of a certain form is the value of a sub-form of it. For example, the
value of a cond is the value of the last form in the selected clause.
In most such cases, if the sub-form produces multiple values, the original
form will also produce all of those values. This passing-back of
multiple values of course has no effect unless eventually one of the
special forms for receiving multiple values is reached.
The exact rule governing passing-back of multiple values is as follows:
If X is a form, and Y is a sub-form of X , then if the value
of Y is unconditionally returned as the value of X , with no
intervening computation, then all the multiple values returned by Y
are returned by X . In all other cases, multiple values or only
single values may be returned at the discretion of the implementation;
users should not depend on this. The reason we don't guarantee
non-transmission of multiple values is because such a guarantee would
not be very useful and the efficiency cost of enforcing it would be
high. Even setq 'ing a variable to the result of a form, then
returning the value of that variable might be made to pass multiple
values by an optimizing compiler which realized that the setq ing of
the variable was unnecessary.
Note that use of a form as an argument to a function never passes-back
multiple values. We choose not to generate several separate arguments
from the several values, because this would make the source code
obscure; it would not be syntactically obvious that a single form does
not coorrespond to a single argument. Instead the first value of a
form is used as the argument and the remaining values are discarded.
Passing-back of multiple values happens only with special forms.
For clarity, the interaction of several common special forms with
multiple values is described. This can all be deduced from the rule
given above.
The body of a defun or a lambda , and variations such as the
body of a function, the body of a let , etc. pass back multiple
values from the last form in the body.
eval , apply , funcall , lexpr-funcall , and <-
pass back multiple values from the function called.
progn passes back multiple values from its last form.
progv does so also.
prog1 and prog2 however do not pass back multiple values.
and and or pass back multiple values from their last form,
but not from previous forms since the return is conditional.
cond passes back multiple values from the last form in the
selected clause, but not if the clause is only one long (i.e. the
returned value is the value of the predicate) since the return is
conditional. This applies even to the last clause where the return
is not really conditional (the implementation is allowed to pass
or not to pass multiple values in this case).
The variants of cond , if , select , selectq , and
dispatch pass back multiple values.
prog passes back the number of values given as arguments to
the return that returns from it. (return form)
may return 1 value or may return all the values of form ; as always
the implementation is not constrained not to return extra values.
(multiple-value-return form) returns from a prog ,
passing back all the values of form .
do behaves like prog with respect to return .
All the values of the last exit-form are returned.
[This is the "right" thing unless you think of the implementation
in terms of return ; what should we do?] *******
unwind-protect does not pass back multiple values.
It clearly should, however this is currently difficult to implement.
This should be fixed later. *******
5.3 Evalhook
evalhook Variable
If the value of evalhook is non-nil , then special things
happen in the evaluator. When a form (even an atom) is to be evaluated,
evalhook is bound to nil and the function which
was evalhook 's value is applied to one argument--the form that was trying
to be evaluated. The value it returns is then returned from the evaluator.
This feature is used by the step program (see LINK:(step-fun)).
evalhook is bound to nil by break and by
the error handler,
and setq 'ed
to nil by errors that go back to top level and print * .
This provides the ability to escape from this mode if something bad
happens.
In order not to impair the efficiency of the Lisp interpreter,
several restrictions are imposed on evalhook .
It only applies to evaluation -- whether in a read-eval-print loop,
internally in evaluating arguments in forms, or by explicit use
of the function eval . It does not have any effect
on compiled function references, on use of the function apply ,
or on the "mapping" functions.
(On the Lisp Machine, as opposed to Maclisp, it is not
necessary to do (*rset t) nor (sstatus evalhook t) .)
store is never seen by the evalhook function; -->
store -->
(Also, Maclisp's special-case check for store is not implemented.)
evalhook
form hook
evalhook is a function which helps
exploit the
evalhook feature. The
form is evaluated
with
evalhook lambda-bound to the functional form
hook .
The checking of
evalhook is bypassed in the evaluation
of
form itself, but not in any subsidiary evaluations,
for instance of arguments in the
form .
This is like a "one-instruction proceed" in a machine-language
debugger.
Example:
;; This function evaluates a form while printing debugging information.
(defun hook (x)
(terpri)
(evalhook x 'hook-function))
;; Notice how this function calls evalhook to evaluate the form f,
;; so as to hook the sub-forms.
(defun hook-function (f)
(let ((v (evalhook f 'hook-function)))
(format t "form: ~s~%value: ~s~%" f v)
v))
The following output might be seen from
(hook '(cons (car '(a . b)) 'c)) :
form: (cons (car (quote (a . b))) (quote c))
form: (car (quote (a . b)))
form: (quote (a . b))
value: (a . b)
value: a
form: (quote c)
value: c
value: (a . c)
(a . c)