Lambda Expressions
------------------
"Lambda expressions" are used to create functions from other Lisp
objects. A lambda expression is a list whose first element is the
symbol `lambda'. All functions written in Lisp (as opposed to the
primitive functions in C) are defined using lambda expressions.
The general format of a lambda expression is:
(lambda LAMBDA-LIST [DOC] [INTERACTIVE-DECLARATION] BODY-FORMS... )
Where LAMBDA-LIST is a list defining the formal parameters of the
function, DOC is an optional documentation string,
INTERACTIVE-DECLARATION is only required by interactive commands (1)
and BODY-FORMS is the sequence of forms making up the function body,
evaluated using an implicit `progn'.
The LAMBDA-LIST is a list, it defines how the values applied to the
function are bound to local variables which represent the parameters of
the function. At its simplest it is simply a list of symbols, each
symbol will have the corresponding argument value bound to it. For
example, the lambda list `(x y)' defines two parameters, `x' and `y'.
When called with two arguments the first will be bound to the variable
`x', the second to `y'. When used in a full lambda expression this
looks like:
(lambda (x y) (+ x y))
this evaluates to an anonymous function with two parameters, `x' and
`y', which when called evaluates to their sum.
Note that a lambda expression itself is _not_ a function, it must be
associated with a lexical environment, this conjunction is usually
called a closure; it is the closure that may be called as a function.
However, to confuse matters, a lambda expression _evaluates_ to the
closure of itself and the current environment. Consider the following
example:
(lambda (x) (1+ x))
=> #<closure>
(functionp (lambda (x) (1+ x)))
=> t
(functionp '(lambda (x) (1+ x)))
=> ()
There are several "lambda-list keywords" which modify the meaning of
symbols in the lambda-list. The syntax of the lambda list is:
([REQUIRED-PARAMETERS...]
[#!optional OPTIONAL-PARAMETERS...]
[#!key KEYWORD-PARAMETERS...]
[#!rest REST-PARAMETER | . REST-PARAMETER])
Each lambda list keyword is a symbol whose name begins `#!', they are
interpreted as follows:
`#!optional'
All variables following this keyword are considered "optional" (all
variables before the first keyword are "required": an error will be
signalled if a required argument is undefined in a function call).
OPTIONAL-PARAMETERS may either be of the form `SYMBOL' or of the
form `(SYMBOL DEFAULT)'. If no argument is supplied for this
parameter the DEFAULT form is evaluated to give the bound
value(2). If no DEFAULT form is given, then the variable is bound
to a false value.
Note that optional parameters must be specified if a later
parameter is also specified.
((lambda (#!optional a b) (list a b)))
=> (() ())
((lambda (#!optional a b) (list a b)) 1)
=> (1 ())
((lambda (#!optional a b) (list a b)) nil 1)
=> (() 1)
((lambda (#!optional (a 1)) (list a)))
=> (1)
((lambda (#!optional (a 1)) (list a)) 2)
=> (2)
`#!key'
This object marks that the parameters up to the next lambda list
keyword are keyword parameters. The values bound to these
parameters when the function is called are determined not by
position (as with normal parameters), but by being marked by a
preceding keyword symbol. Keyword symbols have the syntax
`#:SYMBOL'.
As with optional parameters, default values may be supplied
through the use of the `(SYMBOL DEFAULT)' syntax. If no default
value is given and no keyword argument of the specified kind is
available, the variable is bound to a false value.
For example, the lambda list `(a #!key b c)' accepts one required
argument, and two optional keyword arguments. The variable `a'
would be bound to the first supplied argument; the variable `b'
would be bound to the argument preceded by the keyword `#:b', or
`()' if no such argument exists. (After extracting required and
optional arguments, each remaining pair of values is checked for
associating a value with each keyword.)
((lambda (a #!key b c) (list a b c)) 1 2 3)
=> (1 () ())
((lambda (a #!key b c) (list a b c)) 1 #:b 2 3)
=> (1 2 ())
((lambda (a #!key b c) (list a b c)) 1 #:b 2 #:c 3)
=> (1 2 3)
((lambda (a #!key b c) (list a b c)) 1 #:c 3 #:b 2)
=> (1 2 3)
`#!rest'
The `#!rest' keyword allows a variable number of arguments to be
applied to a function, all the argument values which have not been
bound to argument variables (or used to mark keyword arguments) are
made into a list and bound to the variable following the `#!rest'
keyword. For example, in
(lambda (x #!rest y) ...)
the first argument, `x', is required. Any other arguments applied
to this function are made into a list and this list is bound to the
variable `y'.
Variable argument functions may also be defined through the Scheme
method of using an improper lambda-list. The previous example is
exactly equivalent to:
(lambda (x . y) ...)
When a function represented by a lambda-list is called the first
action is to bind the argument values to the formal parameters. The
LAMBDA-LIST and the list of argument values applied to the function are
worked through in parallel. Any required arguments which are left
undefined when the end of the argument values has been reached causes
an error.
After the arguments have been processed the BODY-FORMS are evaluated
by an implicit progn, the value of which becomes the value of the
function call. Finally, all parameters are unbound and control passes
back to the caller.
---------- Footnotes ----------
(1) Only used when `librep' is embedded within another application.
(2) The DEFAULT form is evaluated in the environment of the closure
being called, but without any of the bindings created by the lambda
expression.