Procedures are first class in Scheme, meaning that procedures can be assigned to variables, passed as arguments to other procedures, be returned from procedures, and be applied to arbitrary arguments. When they are created, procedures ``capture'' variables that are free in their bodies. Because of this ``closing over,'' procedures are also known as closures in Scheme.
Closures can be used for a wide variety of purposes. They can be used to represent objects in an object-oriented framework, to model actors, to represent partially computed solutions, etc.
Unnamed procedures are created with the lambda
special form.
The existence of unnamed procedures frees the programmer from making
up names for simple helper functions. For example, many Scheme
implementations have a sort
procedure that accepts a list or
vector of elements, and a comparison procedure that is used to
establish an ordering on the elements. It is often useful to use an
unnamed procedure as the comparison function:
> (sort '(1 6 3 4) (lambda (n1 n2) (< n1 n2))) (1 3 4 6) > (sort #("jim" "brent" "jason" "todd") (lambda (s1 s2) (string<? s1 s2))) #("brent" "jason" "jim" "todd")
Note that (1 2 3 4)
is a list of numbers and
#("jim" ...)
is a vector of strings.
The next example shows the definition of a procedure
make-counter
that returns another procedure created with
lambda
that closes over the count
variable.
> (define (make-counter) (let ((count 0)) (lambda () (set! count (+ count 1)) count))) make-counter > (define c1 (make-counter)) c1 > (c1) 1 > (c1) 2
Since no one else has access to count
it becomes private to the
closure and can be modified and used within its context. In this
particular case, count
is incremented and its value returned
when the procedure returned from make-counter
is called.