An ordinary lambda list is used to describe how a set of arguments is received by an ordinary function. The defined names in the next figure are those which use ordinary lambda lists:
|
Figure 3.12: Standardized Operators that use Ordinary Lambda Lists
An ordinary lambda list can contain the lambda list keywords shown in the next figure.
|
Figure 3.13: Lambda List Keywords used by Ordinary Lambda Lists
Each element of a lambda list is either a parameter specifier
or a lambda list keyword.
Implementations are free to provide additional lambda list keywords.
For a list of all lambda list keywords
used by the implementation, see lambda-list-keywords
.
The syntax for ordinary lambda lists is as follows:
[
&key {var ({var | (keyword-name var)} [init-form [supplied-p-parameter]])}* [&allow-other-keys]]
A var or supplied-p-parameter must be a symbol that is not the name of a constant variable.
An init-form can be any form. Whenever any init-form is evaluated for any parameter specifier, that form may refer to any parameter variable to the left of the specifier in which the init-form appears, including any supplied-p-parameter variables, and may rely on the fact that no other parameter variable has yet been bound (including its own parameter variable).
A keyword-name can be any symbol, but by convention is normally a keyword1; all standardized functions follow that convention.
An ordinary lambda list has five parts, any or all of which may be empty. For information about the treatment of argument mismatches, see Section 3.5 (Error Checking in Function Calls).
These are all the parameter specifiers up to
the first lambda list keyword;
if there are no lambda list keywords,
then all the specifiers are for required parameters.
Each required parameter is specified by a parameter variable var.
var is bound as a lexical variable unless it is declared special
.
If there are n
required parameters (n
may be zero),
there must be at least n
passed arguments, and the
required parameters are bound to the first n
passed arguments;
see Section 3.5 (Error Checking in Function Calls).
The other parameters are then processed using any remaining arguments.
If &optional
is present,
the optional parameter specifiers are those following
&optional
up to the next lambda list keyword or the end of the list.
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 init-form
is evaluated, and the parameter variable
is bound to the resulting value
(or to nil
if no init-form appears
in the parameter specifier).
If another variable name supplied-p-parameter
appears in the specifier, it is bound
to true if an argument had been available, and to false if no
argument remained (and therefore init-form had to be evaluated).
Supplied-p-parameter
is bound not to an argument but to a value indicating whether or not
an argument had been supplied for the corresponding var.
&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. 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 an error
should be signaled if
any unprocessed arguments remain; see Section 3.5 (Error Checking in Function Calls).
The value of a rest parameter
is permitted, but not required, to share structure with the
last argument to apply
.
If &key
is present, all specifiers up to the next lambda list keyword
or the end of the list are keyword parameter specifiers.
When keyword parameters are processed,
the same arguments are processed that
would be made into a list for a rest parameter.
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.
If &key
is specified, there must remain
an even number of arguments; see Section 3.5.1.6 (Odd Number of Keyword Arguments).
These arguments are considered as pairs,
the first argument in each pair being interpreted as a name
and the second as the corresponding value.
The first object of each pair must be a symbol;
see Section 3.5.1.5 (Invalid Keyword Arguments).
The keyword parameter specifiers may optionally be followed by the
lambda list keyword &allow-other-keys
.
In each keyword parameter specifier must be a name var for
the parameter variable.
If the var appears alone or in a (
var init-form)
combination, the keyword name used when matching arguments to parameters
is a symbol in the KEYWORD
package whose name is the
same (under string=
) as var's.
If the notation ((
keyword-name var)
init-form)
is used,
then the keyword name used to match arguments to parameters is
keyword-name, which may be a symbol in any package.
(Of course, if it is not a symbol in the KEYWORD
package,
it does not necessarily self-evaluate, so care must be taken when calling the function
to make sure that normal evaluation still yields the keyword name.)
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 name matches that
specifier's 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, the leftmost argument pair is used. If no such argument pair
exists, then the init-form for that specifier is evaluated and
the parameter variable is bound to that value (or to nil
if no
init-form was specified). supplied-p-parameter is
treated as for &optional
parameters: it is bound to true if there
was a matching argument pair, and to false otherwise.
Unless keyword argument checking is suppressed, an argument pair must a name matched by a parameter specifier; see Section 3.5.1.4 (Unrecognized Keyword Arguments).
If keyword argument checking is suppressed, then it is permitted for an argument pair to match no parameter specifier, and the argument pair is ignored, but such an argument pair is accessible through the rest parameter if one was supplied. The purpose of these mechanisms is to allow sharing of argument lists among several lambda expressions and to allow either the caller or the called lambda expression to specify that such sharing may be taking place.
Note that if &key
is present, a keyword argument of :allow-other-keys
is always permitted—regardless of whether the associated value is true
or false. However, if the value is false, other non-matching
keywords are not tolerated (unless &allow-other-keys
was used).
Furthermore, if the receiving argument list specifies a regular argument which would be flagged by :allow-other-keys, then :allow-other-keys has both its special-cased meaning (identifying whether additional keywords are permitted) and its normal meaning (data flow into the function in question).
If &allow-other-keys
was specified in the lambda list of a function,
keyword2 argument checking is suppressed in calls
to that function.
If the :allow-other-keys argument is true in a call to a function, keyword2 argument checking is suppressed in that call.
The :allow-other-keys argument is permissible in all situations involving keyword2 arguments, even when its associated value is false.
;;; The caller can supply :ALLOW-OTHER-KEYS T to suppress checking. ((lambda (&key x) x) :x 1 :y 2 :allow-other-keys t) → 1 ;;; The callee can use &ALLOW-OTHER-KEYS to suppress checking. ((lambda (&key x &allow-other-keys) x) :x 1 :y 2) → 1 ;;; :ALLOW-OTHER-KEYS NIL is always permitted. ((lambda (&key) t) :allow-other-keys nil) → T ;;; As with other keyword arguments, only the left-most pair ;;; named :ALLOW-OTHER-KEYS has any effect. ((lambda (&key x) x) :x 1 :y 2 :allow-other-keys t :allow-other-keys nil) → 1 ;;; Only the left-most pair named :ALLOW-OTHER-KEYS has any effect, ;;; so in safe code this signals a PROGRAM-ERROR (and might enter the ;;; debugger). In unsafe code, the consequences are undefined. ((lambda (&key x) x) ;This call is not valid :x 1 :y 2 :allow-other-keys nil :allow-other-keys t)
&aux
variables
These are not really parameters. If the lambda list keyword
&aux
is present, all specifiers after it are auxiliary variable
specifiers. After all parameter specifiers have been processed, the
auxiliary variable specifiers (those following &aux) are processed
from left to right. For each one, init-form is evaluated and
var is bound to that value (or to nil
if no init-form
was specified). &aux
variable processing is analogous to
let*
processing.
(lambda (x y &aux (a (car x)) (b 2) c) (list x y a b c)) ≡ (lambda (x y) (let* ((a (car x)) (b 2) c) (list x y a b c)))
Here are some examples involving optional parameters 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))
Here are some examples involving keyword 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) ((lambda (a b &key ((:sea c)) d) (list a b c d)) 1 2 :sea 6) → (1 2 6 NIL) ((lambda (a b &key ((c c)) d) (list a b c d)) 1 2 'c 6) → (1 2 6 NIL)
Here are some examples involving optional parameters, rest parameters, and keyword parameters together:
((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))
As an example of the use of &allow-other-keys
and
:allow-other-keys, consider a function that takes two named
arguments of its own and also accepts additional named arguments to be
passed to make-array
:
(defun array-of-strings (str dims &rest named-pairs &key (start 0) end &allow-other-keys) (apply #'make-array dims :initial-element (subseq str start end) :allow-other-keys t named-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 named
arguments may be used 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 supply additional named arguments; the rest parameter
provides access to them. These additional named arguments are passed
to make-array
. The function make-array
normally does not allow the named arguments :start
and :end to be used, and an error should be
signaled if such named arguments are supplied to make-array
.
However, the presence in the call to make-array
of the named argument :allow-other-keys with
a true value causes any extraneous named arguments, including
:start and :end, to be acceptable and ignored.