Common Lisp the Language, 2nd Edition
Next: Top-Level Forms
Up: Functions
Previous: Named Functions
A lambda-expression is a list with the following syntax:
(lambda lambda-list . body)
The first element must be the symbol lambda
. The second
element must be a list. It is called the lambda-list, and
specifies names for the parameters of the function. When the
function denoted by the lambda-expression is applied to arguments, the
arguments are matched with the parameters specified by the lambda-list.
The body may then refer to the arguments by using the parameter
names. The body consists of any number of forms (possibly
zero). These forms are evaluated in sequence, and the results of the
last form only are returned as the results of the application
(the value nil
is returned if there are zero forms in the
body). The complete syntax of a lambda-expression is:
(lambda ({var}*
[&optional {var | (var [initform [svar]])}*]
[&rest var]
[&key {var | ({var | (keyword var)} [initform [svar]])}*
[&allow-other-keys]]
[&aux {var | (var [initform])}*)]
[[{declaration}* | documentation-string]]
{form}*)
Each element of a lambda-list is either a parameter
specifier or a lambda-list keyword; lambda-list keywords
begin with &
. (Note that lambda-list keywords are not
keywords in the usual sense; they do not belong to the keyword package.
They are ordinary symbols each of whose names begins with an ampersand.
This terminology is unfortunately confusing but is retained for
historical reasons.)
In all cases a var or svar must be a symbol, the name
of a variable; each keyword must be a keyword symbol, such as
:start
. An initform may be any form.
X3J13 voted in March 1988 (KEYWORD-ARGUMENT-NAME-PACKAGE) to allow a
keyword in the preceding specification of a lambda-list to be
any symbol whatsoever, not just a keyword symbol in the
keyword
package. See below.
A lambda-list has five parts, any or all of which may be empty:
&optional
is present, the optional
parameter specifiers are those following the lambda-list keyword
&optional
up to the next lambda-list keyword or the end
of the list.&rest
, if present, must be followed by a single
rest parameter specifier, which in turn must be followed by
another lambda-list keyword or the end of the lambda-list.&key
is present, all specifiers up to the next
lambda-list keyword or the end of the list are keyword
parameter specifiers. The keyword parameter specifiers may optionally be
followed by the lambda-list keyword
&allow-other-keys
.&key
is present,
all specifiers after it are auxiliary variable specifiers.When the function represented by the lambda-expression is applied to
arguments, the arguments and parameters are processed in order from left
to right. In the simplest case, only required parameters are present in
the lambda-list; each is specified simply by a name var for the
parameter variable. When the function is applied, there must be exactly
as many arguments as there are parameters, and each parameter is bound
to one argument. Here, and in general, the parameter is bound as a
lexical variable unless a declaration has been made that it should be a
special binding; see defvar
, proclaim
, and
declare
.
In the more general case, if there are n required parameters (n may be zero), there must be at least n arguments, and the required parameters are bound to the first n arguments. The other parameters are then processed using any remaining arguments.
If optional parameters are specified, then each one is
processed as follows. If any unprocessed arguments remain, then the
parameter variable var is bound to the next remaining argument,
just as for a required parameter. If no arguments remain, however, then
the initform part of the parameter specifier is evaluated, and
the parameter variable is bound to the resulting value (or to
nil
if no initform appears in the parameter
specifier). If another variable name svar appears in the
specifier, it is bound to true if an argument was available,
and to false if no argument remained (and therefore
initform had to be evaluated). The variable svar is
called a supplied-p parameter; it is bound not to an argument
but to a value indicating whether or not an argument had been supplied
for another parameter.
After all optional parameter specifiers have been processed, then there may or may not be a rest parameter. If there is a rest parameter, it is bound to a list of all as-yet-unprocessed arguments. (If no unprocessed arguments remain, the rest parameter is bound to the empty list.) If there is no rest parameter and there are no keyword parameters, then there should be no unprocessed arguments (it is an error if there are).
X3J13 voted in January 1989 (REST-LIST-ALLOCATION) to clarify that if
a function has a rest parameter and is called using
apply
, then the list to which the rest parameter
is bound is permitted, but not required, to share top-level list
structure with the list that was the last argument to
apply
. Programmers should be careful about performing side
effects on the top-level list structure of a rest
parameter.
This was the result of a rather long discussion within X3J13 and the
wider Lisp community. To set it in its historical context, I must remark
that in Lisp Machine Lisp the list to which a rest parameter
was bound had only dynamic extent; this in conjunction with the
technique of ``cdr-coding’’ permitted a clever stack-allocation
technique with very low overhead. However, the early designers of Common
Lisp, after a great deal of debate, concluded that it was dangerous for
cons cells to have dynamic extent; as an example, the ``obvious’’
definition of the function list
(defun list (&rest x) x)
could fail catastrophically. Therefore the first edition simply
implied that the list for a rest parameter, like all other
lists, would have indefinite extent. This still left open the flip side
of the question, namely, Is the list for a rest parameter
guaranteed fresh? This is the question addressed by the X3J13 vote. If
it is always freshly consed, then it is permissible to destroy it, for
example by giving it to nconc
. However, the requirement
always to cons fresh lists could impose an unacceptable overhead in many
implementations. The clarification approved by X3J13 specifies that the
programmer may not rely on the list being fresh; if the function was
called using apply
, there is no way to know where the list
came from.
Next, any keyword parameters are processed. For this purpose
the same arguments are processed that would be made into a list for a
rest parameter. (Indeed, it is permitted to specify both
&rest
and &key
. In this case the
remaining arguments are used for both purposes; that is, all remaining
arguments are made into a list for the &rest
parameter
and are also processed for the &key
parameters. This is
the only situation in which an argument is used in the processing of
more than one parameter specifier.) If &key
is
specified, there must remain an even number of arguments; these are
considered as pairs, the first argument in each pair being interpreted
as a keyword name and the second as the corresponding value.
It is an error for the first object of each pair to be anything but a
keyword.
Rationale: This last restriction is imposed so that a compiler may issue warnings about certain malformed calls to functions that take keyword arguments. It must be remembered that the arguments in a function call that evaluate to keywords are just like any other arguments and may be any evaluable forms. A compiler could not, without additional context, issue a warning about the call
(fill seq item x y)
because in principle the variable x
might have as its
value a keyword such as :start
. However, a compiler would
be justified in issuing a warning about the call
(fill seq item 0 10)
because the constant 0
is definitely not a keyword.
Similarly, if in the first case the variable x
had been
declared to be of type integer
, then type analysis could
enable the compiler to justify a warning.
X3J13 voted in March 1988 (KEYWORD-ARGUMENT-NAME-PACKAGE) to allow a
keyword in a lambda-list to be any symbol whatsoever, not just
a keyword symbol in the keyword
package. If, after
&key
, a variable appears alone or within only one set
of parentheses (possibly with an initform and a svar),
then the behavior is as before: a keyword symbol with the same name as
the variable is used as the keyword-name when matching arguments to
parameter specifiers. Only a parameter specifier of the form
((
keyword
var
) ...)
can cause the keyword-name not to be a keyword symbol, by specifying a
symbol not in the keyword
package as the keyword.
For example:
(defun wager (&key ((secret password) nil) amount)
(format nil "You ~A $~D"
(if (eq password 'joe-sent-me) "win" "lose")
amount))
(wager :amount 100) => "You lose $100"
(wager :amount 100 'secret 'joe-sent-me) => "You win $100"
The secret
word could be made even more secret in this
example by placing it in some other obscure
package, so
that one would have to write
(wager :amount 100 'obscure:secret 'joe-sent-me) => "You win $100"
to win anything.
In each keyword parameter specifier must be a name var for
the parameter variable. If an explicit keyword is specified,
then that is the keyword name for the parameter. Otherwise the name
var serves to indicate the keyword name, in that a keyword with
the same name (in the keyword
package) is used as the
keyword. Thus
(defun foo (&key radix (type 'integer)) ...)
means exactly the same as
(defun foo (&key ((:radix radix)) ((:type type) 'integer)) ...)
The keyword parameter specifiers are, like all parameter specifiers,
effectively processed from left to right. For each keyword parameter
specifier, if there is an argument pair whose keyword name matches that
specifier’s keyword name (that is, the names are eq
), then
the parameter variable for that specifier is bound to the second item
(the value) of that argument pair. If more than one such argument pair
matches, it is not an error; the leftmost argument pair is used. If no
such argument pair exists, then the initform for that specifier
is evaluated and the parameter variable is bound to that value (or to
nil
if no initform was specified). The variable
svar is treated as for ordinary optional parameters:
it is bound to true if there was a matching argument pair, and
to false otherwise.
It is an error if an argument pair has a keyword name not matched by any parameter specifier, unless at least one of the following two conditions is met:
&allow-other-keys
was specified in the
lambda-list.:allow-other-keys
and whose value is not
nil
.If either condition obtains, then it is not an error for an argument
pair to match no parameter specified, and the argument pair is simply
ignored (but such an argument pair is accessible through the
&rest
parameter if one was specified). The purpose of
these mechanisms is to allow sharing of argument lists among several
functions and to allow either the caller or the called function to
specify that such sharing may be taking place.
After all parameter specifiers have been processed, the auxiliary
variable specifiers (those following the lambda-list keyword
&aux
) are processed from left to right. For each one,
the initform is evaluated and the variable var bound
to that value (or to nil
if no initform was
specified). Nothing can be done with &aux
variables
that cannot be done with the special form let*
:
(lambda (x y &aux (a (car x)) (b 2) c) ...)
== (lambda (x y) (let* ((a (car x)) (b 2) c) ...))
Which to use is purely a matter of style.
Whenever any initform is evaluated for any parameter specifier, that form may refer to any parameter variable to the left of the specifier in which the initform appears, including any supplied-p variables, and may rely on the fact that no other parameter variable has yet been bound (including its own parameter variable).
Once the lambda-list has been processed, the forms in the body of the
lambda-expression are executed. These forms may refer to the arguments
to the function by using the names of the parameters. On exit from the
function, either by a normal return of the function’s value(s) or by a
non-local exit, the parameter bindings, whether lexical or special, are
no longer in effect. (The bindings are not necessarily permanently
discarded, for a lexical binding can later be reinstated if a
``closure’’ over that binding was created, perhaps by using
function
, and saved before the exit occurred.)
Examples of &optional
and &rest
parameters:
((lambda (a b) (+ a (* b 3))) 4 5) => 19
((lambda (a &optional (b 2)) (+ a (* b 3))) 4 5) => 19
((lambda (a &optional (b 2)) (+ a (* b 3))) 4) => 10
((lambda (&optional (a 2 b) (c 3 d) &rest x) (list a b c d x)))
=> (2 nil 3 nil nil)
((lambda (&optional (a 2 b) (c 3 d) &rest x) (list a b c d x))
6)
=> (6 t 3 nil nil)
((lambda (&optional (a 2 b) (c 3 d) &rest x) (list a b c d x))
6 3)
=> (6 t 3 t nil)
((lambda (&optional (a 2 b) (c 3 d) &rest x) (list a b c d x))
6 3 8)
=> (6 t 3 t (8))
((lambda (&optional (a 2 b) (c 3 d) &rest x) (list a b c d x))
6 3 8 9 10 11)
=> (6 t 3 t (8 9 10 11))
Examples of &key
parameters:
((lambda (a b &key c d) (list a b c d)) 1 2)
=> (1 2 nil nil)
((lambda (a b &key c d) (list a b c d)) 1 2 :c 6)
=> (1 2 6 nil)
((lambda (a b &key c d) (list a b c d)) 1 2 :d 8)
=> (1 2 nil 8)
((lambda (a b &key c d) (list a b c d)) 1 2 :c 6 :d 8)
=> (1 2 6 8)
((lambda (a b &key c d) (list a b c d)) 1 2 :d 8 :c 6)
=> (1 2 6 8)
((lambda (a b &key c d) (list a b c d)) :a 1 :d 8 :c 6)
=> (:a 1 6 8)
((lambda (a b &key c d) (list a b c d)) :a :b :c :d)
=> (:a :b :d nil)
Examples of mixtures:
((lambda (a &optional (b 3) &rest x &key c (d a))
(list a b c d x))
1) => (1 3 nil 1 ())
((lambda (a &optional (b 3) &rest x &key c (d a))
(list a b c d x))
1 2) => (1 2 nil 1 ())
((lambda (a &optional (b 3) &rest x &key c (d a))
(list a b c d x))
:c 7) => (:c 7 nil :c ())
((lambda (a &optional (b 3) &rest x &key c (d a))
(list a b c d x))
1 6 :c 7) => (1 6 7 1 (:c 7))
((lambda (a &optional (b 3) &rest x &key c (d a))
(list a b c d x))
1 6 :d 8) => (1 6 nil 8 (:d 8))
((lambda (a &optional (b 3) &rest x &key c (d a))
(list a b c d x))
1 6 :d 8 :c 9 :d 10) => (1 6 9 8 (:d 8 :c 9 :d 10))
All lambda-list keywords are permitted, but not terribly useful, in
lambda-expressions appearing explicitly as the first element of a
function-call form. They are extremely useful, however, in functions
given global names by defun
.
All symbols whose names begin with &
are
conventionally reserved for use as lambda-list keywords and should not
be used as variable names. Implementations of Common Lisp are free to
provide additional lambda-list keywords.
[Constant]
lambda-list-keywords
The value of lambda-list-keywords
is a list of all the
lambda-list keywords used in the implementation, including the
additional ones used only by defmacro
. This list must
contain at least the symbols &optional
,
&rest
, &key
,
&allow-other-keys
, &aux
,
&body
, &whole
, and
&environment
.
As an example of the use of &allow-other-keys
and
:allow-other-keys
, consider a function that takes two
keyword arguments of its own and also accepts additional keyword
arguments to be passed to make-array
:
(defun array-of-strings (str dims &rest keyword-pairs
&key (start 0) end &allow-other-keys)
(apply #'make-array dims
:initial-element (subseq str start end)
:allow-other-keys t
keyword-pairs))
This function takes a string and dimensioning information and returns
an array of the specified dimensions, each of whose elements is the
specified string. However, :start
and :end
keyword arguments may be used in the usual manner (see chapter 14) to specify that a substring of the
given string should be used. In addition, the presence of
&allow-other-keys
in the lambda-list indicates that the
caller may specify additional keyword arguments; the
&rest
argument provides access to them. These
additional keyword arguments are fed to make-array
. Now,
make-array
normally does not allow the keywords
:start
and :end
to be used, and it would be an
error to specify such keyword arguments to make-array
.
However, the presence in the call to make-array
of the
keyword argument :allow-other-keys
with a
non-nil
value causes any extraneous keyword arguments,
including :start
and :end
, to be acceptable
and ignored.
[Constant]
lambda-parameters-limit
The value of lambda-parameters-limit
is a positive
integer that is the upper exclusive bound on the number of distinct
parameter names that may appear in a single lambda-list. This bound
depends on the implementation but will not be smaller than 50.
Implementors are encouraged to make this limit as large as practicable
without sacrificing performance. See
call-arguments-limit
.
Next: Top-Level Forms
Up: Functions
Previous: Named Functions
AI.Repository@cs.cmu.edu