Next: Dynamic Binding, Up: Scoping Rules for Variable Bindings [Contents][Index]
Lexical binding is only available in the modern Emacs Lisp dialect. (See Selecting Lisp Dialect.) A lexically-bound variable has lexical scope, meaning that any reference to the variable must be located textually within the binding construct. Here is an example
(let ((x 1)) ;x
is lexically bound. (+ x 3)) ⇒ 4 (defun getx () x) ;x
is used free in this function. (let ((x 1)) ;x
is lexically bound. (getx)) error→ Symbol's value as variable is void: x
Here, the variable x
has no global value. When it is lexically
bound within a let
form, it can be used in the textual confines
of that let
form. But it can not be used from within a
getx
function called from the let
form, since the
function definition of getx
occurs outside the let
form
itself.
Here is how lexical binding works. Each binding construct defines a lexical environment, specifying the variables that are bound within the construct and their local values. When the Lisp evaluator wants the current value of a variable, it looks first in the lexical environment; if the variable is not specified in there, it looks in the symbol’s value cell, where the dynamic value is stored.
Lexical bindings have indefinite extent. Even after a binding construct has finished executing, its lexical environment can be “kept around” in Lisp objects called closures. A closure is created when you define a named or anonymous function with lexical binding enabled. See Closures, for details.
When a closure is called as a function, any lexical variable references within its definition use the retained lexical environment. Here is an example:
(defvar my-ticker nil) ; We will use this dynamically bound ; variable to store a closure. (let ((x 0)) ;x
is lexically bound. (setq my-ticker (lambda () (setq x (1+ x))))) ⇒ #f(lambda () [(x 0)] (setq x (1+ x))) (funcall my-ticker) ⇒ 1 (funcall my-ticker) ⇒ 2 (funcall my-ticker) ⇒ 3 x ; Note thatx
has no global value. error→ Symbol's value as variable is void: x
Here, the let
binding defines a lexical environment in which the
variable x
is locally bound to 0. Within this binding
construct, we define a lambda expression which increments x
by
one and returns the incremented value. This lambda expression is
automatically turned into a closure, in which the lexical environment
lives on even after the let
binding construct has exited. Each
time we evaluate the closure, it increments x
, using the
binding of x
in that lexical environment.
Note that unlike dynamic variables which are tied to the symbol
object itself, the relationship between lexical variables and symbols
is only present in the interpreter (or compiler). Therefore,
functions which take a symbol argument (like symbol-value
,
boundp
, and set
) can only retrieve or modify a
variable’s dynamic binding (i.e., the contents of its symbol’s value
cell).
Note also that variables may be declared special, in which case they
will use dynamic binding, even for new bindings such as a let
binding. Depending on how the variable is declared, it can be
special globally, for a single file, or for a portion of a file.
See Dynamic Binding for details.
Next: Dynamic Binding, Up: Scoping Rules for Variable Bindings [Contents][Index]