5.2 Issues in multitasking
Common Lisp uses function objects called lexical closures to hold the values of lexical variables that are needed beyond their normal lifetime.
For example, consider the following code:
> (setq lexical-closure (let ((a 0)) #'(lambda (key) (cond ((eq key :increment) (incf a)) ((eq key :value) a) (t (error "Unknown operation ~A" key)))))) #<Interpreted-Function (LAMBDA (KEY) (COND ((EQ KEY :INCREMENT) (INCF A)) ((EQ KEY :VALUE) A) (T (ERROR "Unknown operation ~A" KEY)))) FB2DA7>The value of
lexical-closure
is a function, created usinglambda
, that refers to the variablea
. Even when thelet
form that created the lexical variablea
has exited, the variable continues to exist as a location that can be modified.Thus, you could enter these expressions with the following results:
> (funcall lexical-closure :increment) 1The special variable> (funcall lexical-closure :increment) 2
> (funcall lexical-closure :value) 2
> (setf a 23) 23
> (funcall lexical-closure :value) 2
a
, whose value has been set to 23, has no relationship to the lexical variablea
, whose value has been saved in a lexical closure.Suppose you used a special variable instead of a lexical variable, as follows:
> (defvar *a* 23) *A*Since> (setq not-lexical-closure (let ((*a* 0)) #'(lambda (key) (cond ((eq key :increment) (incf *a*)) ((eq key :value) *a*) (t (error "Unknown operation ~A" key)))))) #<Interpreted-Function (LAMBDA (KEY) (COND ((EQ KEY :INCREMENT) (INCF *A*)) ((EQ KEY :VALUE) *A*) (T (ERROR "Unknown operation ~A" KEY)))) FB3247>
> (funcall not-lexical-closure :increment) 24
*a*
is a special variable, no lexical closure is created. The value of the variablenot-lexical-closure
is a function that accesses and increments the current symbol value of the symbol*a*
. Lexical closures can be used for communication between processes. For example, a process with a lexical variable namedinfo
can create the following function:
#'(lambda (new-value) (setf info new-value))The parent process can pass this function as an argument to any other process it creates. The created process can use the Common Lisp function
funcall
with this argument to set the value of the parent process's lexical variable.
Generated with Harlequin WebMaker