lambda expression evaluates to a procedure. The environment in
effect when the
lambda expression is evaluated is remembered as
part of the procedure; it is called the closing environment. When
the procedure is later called with some arguments, the closing
environment is extended by binding the variables in the formal parameter
list to fresh locations, and the locations are filled with the arguments
according to rules about to be given. The new environment created by
this process is referred to as the invocation environment.
Once the invocation environment has been constructed, the exprs
in the body of the
lambda expression are evaluated sequentially
in it. This means that the region of the variables bound by the
lambda expression is all of the exprs in the body. The
result of evaluating the last expr in the body is returned as
the result of the procedure call.
Formals, the formal parameter list, is often referred to as a lambda list.
The process of matching up formal parameters with arguments is somewhat involved. There are three types of parameters, and the matching treats each in sequence:
All of the required parameters are matched against the arguments
first. If there are fewer arguments than required parameters, an error
condition-type:wrong-number-of-arguments is signalled;
this error is also signalled if there are more arguments than required
parameters and there are no further parameters.
Once the required parameters have all been matched, the optional
parameters are matched against the remaining arguments. If there are
fewer arguments than optional parameters, the unmatched parameters are
bound to special objects called default objects. If there are
more arguments than optional parameters, and there are no further
parameters, an error of type
condition-type:wrong-number-of-arguments is signalled.
default-object?, which is true only of default
objects, can be used to determine which optional parameters were
supplied, and which were defaulted.
Finally, if there is a rest parameter (there can only be one), any remaining arguments are made into a list, and the list is bound to the rest parameter. (If there are no remaining arguments, the rest parameter is bound to the empty list.)
In Scheme, unlike some other Lisp implementations, the list to which a rest parameter is bound is always freshly allocated. It has infinite extent and may be modified without affecting the procedure’s caller.
Specially recognized keywords divide the formals parameters into these three classes. The keywords used here are ‘#!optional’, ‘.’, and ‘#!rest’. Note that only ‘.’ is defined by standard Scheme — the other keywords are MIT/GNU Scheme extensions. ‘#!rest’ has the same meaning as ‘.’ in formals.
The use of these keywords is best explained by means of examples. The following are typical lambda lists, followed by descriptions of which parameters are required, optional, and rest. We will use ‘#!rest’ in these examples, but anywhere it appears ‘.’ could be used instead.
(a b c)
c are all required. The procedure must
be passed exactly three arguments.
(a b #!optional c)
b are required,
c is optional. The procedure
may be passed either two or three arguments.
(#!optional a b c)
c are all optional. The procedure may be
passed any number of arguments between zero and three, inclusive.
These two examples are equivalent.
a is a rest parameter. The
procedure may be passed any number of arguments. Note: this is the only
case in which ‘.’ cannot be used in place of ‘#!rest’.
(a b #!optional c d #!rest e)
b are required,
d are optional,
e is rest. The procedure may be passed two or more
Some examples of
(lambda (x) (+ x x)) ⇒ #[compound-procedure 53] ((lambda (x) (+ x x)) 4) ⇒ 8 (define reverse-subtract (lambda (x y) (- y x))) (reverse-subtract 7 10) ⇒ 3 (define foo (let ((x 4)) (lambda (y) (+ x y)))) (foo 6) ⇒ 10
named-lambda special form is similar to
that the first “required parameter” in formals is not a
parameter but the name of the resulting procedure; thus
formals must have at least one required parameter. This name has
no semantic meaning, but is included in the external representation of
the procedure, making it useful for debugging. In MIT/GNU Scheme,
lambda is implemented as
named-lambda, with a special name
that means “unnamed”.
(named-lambda (f x) (+ x x)) ⇒ #[compound-procedure 53 f] ((named-lambda (f x) (+ x x)) 4) ⇒ 8