cl: Obsolete Lexical Binding
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 ((elisp)Closures). 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*’.