lambdaexpression evaluates to a procedure. The environment in effect when the
lambdaexpression 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 expressions in the body of the
lambdaexpression are evaluated sequentially in it. This means that the region of the variables bound by the
lambdaexpression is all of the expressions in the body. The result of evaluating the last expression in the body is returned as the result of the procedure call.
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 of type
condition-type:wrong-number-of-argumentsis 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-argumentsis signalled. The predicate
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)
care all required. The procedure must be passed exactly three arguments.
(a b #!optional c)
cis optional. The procedure may be passed either two or three arguments.
(#!optional a b c)
care all optional. The procedure may be passed any number of arguments between zero and three, inclusive.
- These two examples are equivalent.
ais 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)
dare optional, and
eis rest. The procedure may be passed two or more arguments.
Some examples of
lambdaexpressions:(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-lambdaspecial form is similar to
lambda, except 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,
lambdais 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