www.delorie.com/gnu/docs/emacs/cl_21.html   search  
 
Buy the book!


Common Lisp Extensions

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.3.2 Lexical Bindings

The CL package defines the following macro which more closely follows the Common Lisp let form:

Special Form: lexical-let (bindings...) forms...
This form is exactly like let except that the bindings it establishes are purely lexical. Lexical bindings are similar to local variables in a language like C: Only the code physically within the body of the lexical-let (after macro expansion) may refer to the bound variables.

 
(setq a 5)
(defun foo (b) (+ a b))
(let ((a 2)) (foo a))
     => 4
(lexical-let ((a 2)) (foo a))
     => 7

In this example, a regular let binding of a actually makes a temporary change to the global variable a, so foo is able to see the binding of a to 2. But lexical-let actually creates a distinct local variable a for use within its body, without any effect on the global variable of the same name.

The most important use of lexical bindings is to create closures. A closure is a function object that refers to an outside lexical variable. For example:

 
(defun make-adder (n)
  (lexical-let ((n n))
    (function (lambda (m) (+ n m)))))
(setq add17 (make-adder 17))
(funcall add17 4)
     => 21

The call (make-adder 17) returns a function object which adds 17 to its argument. If let had been used instead of lexical-let, the function object would have referred to the global n, which would have been bound to 17 only during the call to make-adder itself.

 
(defun make-counter ()
  (lexical-let ((n 0))
    (function* (lambda (&optional (m 1)) (incf n m)))))
(setq count-1 (make-counter))
(funcall count-1 3)
     => 3
(funcall count-1 14)
     => 17
(setq count-2 (make-counter))
(funcall count-2 5)
     => 5
(funcall count-1 2)
     => 19
(funcall count-2)
     => 6

Here we see that each call to make-counter creates a distinct local variable n, which serves as a private counter for the function object that is returned.

Closed-over lexical variables persist until the last reference to them goes away, just like all other Lisp objects. For example, count-2 refers to a function object which refers to an instance of the variable n; this is the only reference to that variable, so after (setq count-2 nil) the garbage collector would be able to delete this instance of n. Of course, if a lexical-let does not actually create any closures, then the lexical variables are free as soon as the lexical-let returns.

Many closures are used only during the extent of the bindings they refer to; these are known as "downward funargs" in Lisp parlance. When a closure is used in this way, regular Emacs Lisp dynamic bindings suffice and will be more efficient than lexical-let closures:

 
(defun add-to-list (x list)
  (mapcar (lambda (y) (+ x y))) list)
(add-to-list 7 '(1 2 5))
     => (8 9 12)

Since this lambda is only used while x is still bound, it is not necessary to make a true closure out of it.

You can use defun or flet inside a lexical-let to create a named closure. If several closures are created in the body of a single lexical-let, they all close over the same instance of the lexical variable.

The lexical-let form is an extension to Common Lisp. In true Common Lisp, all bindings are lexical unless declared otherwise.

Special Form: lexical-let* (bindings...) forms...
This form is just like lexical-let, except that the bindings are made sequentially in the manner of let*.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

  webmaster   donations   bookstore     delorie software   privacy  
  Copyright 2003   by The Free Software Foundation     Updated Jun 2003