Next: , Up: Obsolete Features   [Contents][Index]

D.1 Obsolete Lexical Binding

The following macros are extensions to Common Lisp, where all bindings are lexical unless declared otherwise. These features are likewise obsolete since the introduction of true lexical binding in Emacs 24.1.

Macro: 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 (see Closures in GNU Emacs Lisp Reference Manual). 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))
    (cl-function (lambda (&optional (m 1)) (cl-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.

Macro: lexical-let* (bindings…) forms…

This form is just like lexical-let, except that the bindings are made sequentially in the manner of let*.

Next: , Up: Obsolete Features   [Contents][Index]