Apropos

3.4 Lambda Lists

A lambda list is a list that specifies a set of parameters (sometimes called lambda variables) and a protocol for receiving values for those parameters.

There are several kinds of lambda lists.

Figure 3–10. What Kind of Lambda Lists to Use

Figure 3–11 lists some defined names that are applicable to lambda lists.

Figure 3–11. Defined names applicable to lambda lists

3.4.1 Ordinary Lambda Lists

An ordinary lambda list is used to describe how a set of arguments is received by an ordinary function. The defined names in Figure 3–12 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 Figure 3–13.

&allow-other-keys &key &rest
&aux &optional
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:

lambda-list::= ({var}*
[&optional {var | (var [init-form [supplied-p-parameter]])}*]
[&rest var]
[&key {var | ({var | (keyword-name var)} [init-form [supplied-p-parameter]])}* [&allow-other-keys]]
[&aux {var | (var [init-form])}*])

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).

3.4.1.1 Specifiers for the required parameters

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.

3.4.1.2 Specifiers for optional parameters

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.

3.4.1.3 A specifier for a rest parameter

&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.

3.4.1.4 Specifiers for keyword parameters

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).

3.4.1.4.1 Suppressing Keyword Argument Checking

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.

3.4.1.4.1.1 Examples of Suppressing Keyword Argument Checking
;;; 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)

3.4.1.5 Specifiers for &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)))

3.4.1.6 Examples of Ordinary Lambda Lists

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.

3.4.2 Generic Function Lambda Lists

A generic function lambda list is used to describe the overall shape of the argument list to be accepted by a generic function. Individual method signatures might contribute additional keyword parameters to the lambda list of the effective method.

A generic function lambda list is used by defgeneric.

A generic function lambda list has the following syntax:

lambda-list::= ({var}*
[&optional {var | (var)}*]
[&rest var]
[&key {var | ({var | (keyword-name var)})}* [&allow-other-keys]])

A generic function lambda list can contain the lambda list keywords shown in Figure 3–14.

&allow-other-keys &optional
&key &rest
Figure 3–14. Lambda List Keywords used by Generic Function Lambda Lists

A generic function lambda list differs from an ordinary lambda list in the following ways:

Required arguments

Zero or more required parameters must be specified.

Optional and keyword arguments

Optional parameters and keyword parameters may not have default initial value forms nor use supplied-p parameters.

Use of &aux

The use of &aux is not allowed.

3.4.3 Specialized Lambda Lists

A specialized lambda list is used to specialize a method for a particular signature and to describe how arguments matching that signature are received by the method. The defined names in Figure 3–15 use specialized lambda lists in some way; see the dictionary entry for each for information about how.

Figure 3–15. Standardized Operators that use Specialized Lambda Lists

A specialized lambda list can contain the lambda list keywords shown in Figure 3–16.

&allow-other-keys &key &rest
&aux &optional
Figure 3–16. Lambda List Keywords used by Specialized Lambda Lists

A specialized lambda list is syntactically the same as an ordinary lambda list except that each required parameter may optionally be associated with a class or object for which that parameter is specialized.

lambda-list::= ({var | (var [specializer])}*
[&optional {var | (var [init-form [supplied-p-parameter]])}*]
[&rest var]
[&key {var | ({var | (keyword-name var)} [init-form [supplied-p-parameter]])}* [&allow-other-keys]]
[&aux {var | (var [init-form])}*])

3.4.4 Macro Lambda Lists

A macro lambda list is used in describing macros defined by the operators in Figure 3–17.

Figure 3–17. Operators that use Macro Lambda Lists

With the additional restriction that an environment parameter may appear only once (at any of the positions indicated), a macro lambda list has the following syntax:

reqvars::= {var | ↓pattern}*
optvars::= [&optional {var | ({var | ↓pattern} [init-form [supplied-p-parameter]])}*]
restvar::= [{&rest | &body} {var | pattern}]
keyvars::= [&key {var | ({var | (keyword-name {var | ↓pattern})} [init-form [supplied-p-parameter]])}*
[&allow-other-keys]]
auxvars::= [&aux {var | (var [init-form])}*]
envvar::= [&environment var]
wholevar::= [&whole var]
lambda-list::= (↓wholevarenvvarreqvarsenvvaroptvarsenvvar
restvarenvvarkeyvarsenvvarauxvarsenvvar) |
(↓wholevarenvvarreqvarsenvvaroptvarsenvvar . var)
pattern::= (↓wholevarreqvarsoptvarsrestvarkeyvarsauxvars) |
(↓wholevarreqvarsoptvars . var)

A macro lambda list can contain the lambda list keywords shown in Figure 3–18.

&allow-other-keys &environment &rest
&aux &key &whole
&body &optional
Figure 3–18. Lambda List Keywords used by Macro Lambda Lists

Optional parameters (introduced by &optional) and keyword parameters (introduced by &key) can be supplied in a macro lambda list, just as in an ordinary lambda list. Both may contain default initialization forms and supplied-p parameters.

&body is identical in function to &rest, but it can be used to inform certain output-formatting and editing functions that the remainder of the form is treated as a body, and should be indented accordingly. Only one of &body or &rest can be used at any particular level; see Section 3.4.4.1 (Destructuring by Lambda Lists). &body can appear at any level of a macro lambda list; for details, see Section 3.4.4.1 (Destructuring by Lambda Lists).

&whole is followed by a single variable that is bound to the entire macro-call form; this is the value that the macro function receives as its first argument. If &whole and a following variable appear, they must appear first in lambda-list, before any other parameter or lambda list keyword. &whole can appear at any level of a macro lambda list. At inner levels, the &whole variable is bound to the corresponding part of the argument, as with &rest, but unlike &rest, other arguments are also allowed. The use of &whole does not affect the pattern of arguments specified.

&environment is followed by a single variable that is bound to an environment representing the lexical environment in which the macro call is to be interpreted. This environment should be used with macro-function, get-setf-expansion, compiler-macro-function, and macroexpand (for example) in computing the expansion of the macro, to ensure that any lexical bindings or definitions established in the compilation environment are taken into account. &environment can only appear at the top level of a macro lambda list, and can only appear once, but can appear anywhere in that list; the &environment parameter is bound along with &whole before any other variables in the lambda list, regardless of where &environment appears in the lambda list. The object that is bound to the environment parameter has dynamic extent.

Destructuring allows a macro lambda list to express the structure of a macro call syntax. If no lambda list keywords appear, then the macro lambda list is a tree containing parameter names at the leaves. The pattern and the macro form must have compatible tree structure; that is, their tree structure must be equivalent, or it must differ only in that some leaves of the pattern match non-atomic objects of the macro form. For information about error detection in this situation, see Section 3.5.1.7 (Destructuring Mismatch).

A destructuring lambda list (whether at top level or embedded) can be dotted, ending in a parameter name. This situation is treated exactly as if the parameter name that ends the list had appeared preceded by &rest.

It is permissible for a macro form (or a subexpression of a macro form) to be a dotted list only when (... &rest var) or (... . var) is used to match it. It is the responsibility of the macro to recognize and deal with such situations.

3.4.4.1 Destructuring by Lambda Lists

Anywhere in a macro lambda list where a parameter name can appear, and where ordinary lambda list syntax (as described in Section 3.4.1 (Ordinary Lambda Lists)) does not otherwise allow a list, a destructuring lambda list can appear in place of the parameter name. When this is done, then the argument that would match the parameter is treated as a (possibly dotted) list, to be used as an argument list for satisfying the parameters in the embedded lambda list. This is known as destructuring.

Destructuring is the process of decomposing a compound object into its component parts, using an abbreviated, declarative syntax, rather than writing it out by hand using the primitive component-accessing functions. Each component part is bound to a variable.

A destructuring operation requires an object to be decomposed, a pattern that specifies what components are to be extracted, and the names of the variables whose values are to be the components.

3.4.4.1.1 Data-directed Destructuring by Lambda Lists

In data-directed destructuring, the pattern is a sample object of the type to be decomposed. Wherever a component is to be extracted, a symbol appears in the pattern; this symbol is the name of the variable whose value will be that component.

3.4.4.1.1.1 Examples of Data-directed Destructuring by Lambda Lists

An example pattern is

(a b c)

which destructures a list of three elements. The variable a is assigned to the first element, b to the second, etc. A more complex example is

((first . rest) . more)

The important features of data-directed destructuring are its syntactic simplicity and the ability to extend it to lambda-list-directed destructuring.

3.4.4.1.2 Lambda-list-directed Destructuring by Lambda Lists

An extension of data-directed destructuring of trees is lambda-list-directed destructuring. This derives from the analogy between the three-element destructuring pattern

(first second third)

and the three-argument lambda list

(first second third)

Lambda-list-directed destructuring is identical to data-directed destructuring if no lambda list keywords appear in the pattern. Any list in the pattern (whether a sub-list or the whole pattern itself) that contains a lambda list keyword is interpreted specially. Elements of the list to the left of the first lambda list keyword are treated as destructuring patterns, as usual, but the remaining elements of the list are treated like a function’s lambda list except that where a variable would normally be required, an arbitrary destructuring pattern is allowed. Note that in case of ambiguity, lambda list syntax is preferred over destructuring syntax. Thus, after &optional a list of elements is a list of a destructuring pattern and a default value form.

The detailed behavior of each lambda list keyword in a lambda-list-directed destructuring pattern is as follows:

&optional

Each following element is a variable or a list of a destructuring pattern, a default value form, and a supplied-p variable. The default value and the supplied-p variable can be omitted. If the list being destructured ends early, so that it does not have an element to match against this destructuring (sub)-pattern, the default form is evaluated and destructured instead. The supplied-p variable receives the value nil if the default form is used, t otherwise.

&rest, &body

The next element is a destructuring pattern that matches the rest of the list. &body is identical to &rest but declares that what is being matched is a list of forms that constitutes the body of form. This next element must be the last unless a lambda list keyword follows it.

&aux

The remaining elements are not destructuring patterns at all, but are auxiliary variable bindings.

&whole

The next element is a destructuring pattern that matches the entire form in a macro, or the entire subexpression at inner levels.

&key

Each following element is one of

a variable,

or

a list of a variable, an optional initialization form, and an optional supplied-p variable.

or

a list of a list of a keyword and a destructuring pattern, an optional initialization form, and an optional supplied-p variable.

The rest of the list being destructured is taken to be alternating keywords and values and is taken apart appropriately.

&allow-other-keys

Stands by itself.

3.4.5 Destructuring Lambda Lists

A destructuring lambda list is used by destructuring-bind.

Destructuring lambda lists are closely related to macro lambda lists; see Section 3.4.4 (Macro Lambda Lists). A destructuring lambda list can contain all of the lambda list keywords listed for macro lambda lists except for &environment, and supports destructuring in the same way. Inner lambda lists nested within a macro lambda list have the syntax of destructuring lambda lists.

A destructuring lambda list has the following syntax:

reqvars::= {var | ↓lambda-list}*
optvars::= [&optional {var | ({var | ↓lambda-list} [init-form [supplied-p-parameter]])}*]
restvar::= [{&rest | &body} {var | lambda-list}]
keyvars::= [&key {var | ({var | (keyword-name {var | ↓lambda-list})} [init-form [supplied-p-parameter]])}*
[&allow-other-keys]]
auxvars::= [&aux {var | (var [init-form])}*]
envvar::= [&environment var]
wholevar::= [&whole var]
lambda-list::= (↓wholevarreqvarsoptvarsrestvarkeyvarsauxvars) |
(↓wholevarreqvarsoptvars . var)

3.4.6 Boa Lambda Lists

A boa lambda list is a lambda list that is syntactically like an ordinary lambda list, but that is processed in “by order of argument” style.

A boa lambda list is used only in a defstruct form, when explicitly specifying the lambda list of a constructor function (sometimes called a “boa constructor”).

The &optional, &rest, &aux, &key, and &allow-other-keys lambda list keywords are recognized in a boa lambda list. The way these lambda list keywords differ from their use in an ordinary lambda list follows.

Consider this example, which describes how defstruct processes its :constructor option.

(:constructor create-foo 
        (a &optional b (c 'sea) &rest d &aux e (f 'eff)))

This defines create-foo to be a constructor of one or more arguments. The first argument is used to initialize the a slot. The second argument is used to initialize the b slot. If there isn’t any second argument, then the default value given in the body of the defstruct (if given) is used instead. The third argument is used to initialize the c slot. If there isn’t any third argument, then the symbol sea is used instead. Any arguments following the third argument are collected into a list and used to initialize the d slot. If there are three or fewer arguments, then nil is placed in the d slot. The e slot is not initialized; its initial value is implementation-defined. Finally, the f slot is initialized to contain the symbol eff. &key and &allow-other-keys arguments default in a manner similar to that of &optional arguments: if no default is supplied in the lambda list then the default value given in the body of the defstruct (if given) is used instead. For example:

 (defstruct (foo (:constructor CREATE-FOO (a &optional b (c 'sea) 
                                             &key (d 2) 
                                             &aux e (f 'eff)))) 
   (a 1) (b 2) (c 3) (d 4) (e 5) (f 6)) 

 (create-foo 10)  #S(FOO A 10 B 2 C SEA D 2 E implemention-dependent F EFF) 
 (create-foo 10 'bee 'see :d 'dee) 
 #S(FOO A 10 B BEE C SEE D DEE E implemention-dependent F EFF)

If keyword arguments of the form ((key var) [default [svar]]) are specified, the slot name is matched with var (not key).

The actions taken in the b and e cases were carefully chosen to allow the user to specify all possible behaviors. The &aux variables can be used to completely override the default initializations given in the body.

If no default value is supplied for an aux variable variable, the consequences are undefined if an attempt is later made to read the corresponding slot’s value before a value is explicitly assigned. If such a slot has a :type option specified, this suppressed initialization does not imply a type mismatch situation; the declared type is only required to apply when the slot is finally assigned.

With this definition, the following can be written:

(create-foo 1 2)

instead of

(make-foo :a 1 :b 2)

and create-foo provides defaulting different from that of make-foo.

Additional arguments that do not correspond to slot names but are merely present to supply values used in subsequent initialization computations are allowed. For example, in the definition

(defstruct (frob (:constructor create-frob 
                 (a &key (b 3 have-b) (c-token 'c) 
                         (c (list c-token (if have-b 7 2)))))) 
        a b c)

the c-token argument is used merely to supply a value used in the initialization of the c slot. The supplied-p parameters associated with optional parameters and keyword parameters might also be used this way.

3.4.7 Defsetf Lambda Lists

A defsetf lambda list is used by defsetf.

A defsetf lambda list has the following syntax:

lambda-list::= ({var}*
[&optional {var | (var [init-form [supplied-p-parameter]])}*]
[&rest var]
[&key {var | ({var | (keyword-name var)} [init-form [supplied-p-parameter]])}* [&allow-other-keys]]
[&environment var]

A defsetf lambda list can contain the lambda list keywords shown in Figure 3–19.

&allow-other-keys &key &rest
&environment &optional
Figure 3–19. Lambda List Keywords used by Defsetf Lambda Lists

A defsetf lambda list differs from an ordinary lambda list only in that it does not permit the use of &aux, and that it permits use of &environment, which introduces an environment parameter.

3.4.8 Deftype Lambda Lists

A deftype lambda list is used by deftype.

A deftype lambda list has the same syntax as a macro lambda list, and can therefore contain the lambda list keywords as a macro lambda list.

A deftype lambda list differs from a macro lambda list only in that if no init-form is supplied for an optional parameter or keyword parameter in the lambda-list, the default value for that parameter is the symbol * (rather than nil).

3.4.9 Define-modify-macro Lambda Lists

A define-modify-macro lambda list is used by define-modify-macro.

A define-modify-macro lambda list can contain the lambda list keywords shown in Figure 3–20.

&optional &rest
Figure 3–20. Lambda List Keywords used by Define-modify-macro Lambda Lists

Define-modify-macro lambda lists are similar to ordinary lambda lists, but do not support keyword arguments. define-modify-macro has no need match keyword arguments, and a rest parameter is sufficient. Aux variables are also not supported, since define-modify-macro has no body forms which could refer to such bindings. See the macro define-modify-macro.

3.4.10 Define-method-combination Arguments Lambda Lists

A define-method-combination arguments lambda list is used by the :arguments option to define-method-combination.

A define-method-combination arguments lambda list can contain the lambda list keywords shown in Figure 3–21.

&allow-other-keys &key &rest
&aux &optional &whole
Figure 3–21. Lambda List Keywords used by Define-method-combination arguments Lambda Lists

Define-method-combination arguments lambda lists are similar to ordinary lambda lists, but also permit the use of &whole.

3.4.11 Syntactic Interaction of Documentation Strings and Declarations

In a number of situations, a documentation string can appear amidst a series of declare expressions prior to a series of forms.

In that case, if a string S appears where a documentation string is permissible and is not followed by either a declare expression or a form then S is taken to be a form; otherwise, S is taken as a documentation string. The consequences are unspecified if more than one such documentation string is present.