In some cases, both lexical and dynamic binding behave identically. However, in other cases, they can change the meaning of your program. For example, see what happens in this code under lexical binding:
;;; -*- lexical-binding: t -*- (setq x 0) (defun getx () x) (setq x 1) (let ((x 2)) (getx)) ⇒ 1
Here, the result of (getx)
is 1
. Under lexical binding,
getx
doesn’t see the value from our let
expression.
That’s because the body of getx
is outside of the body of our
let
expression. Since getx
is defined at the top,
global level of our code (i.e. not inside the body of any let
expression), it looks for and finds x
at the global level as
well. When executing getx
, the current global value of
x
is 1
, so that’s what getx
returns.
If we use dynamic binding instead, the behavior is different:
;;; -*- lexical-binding: nil -*- (setq x 0) (defun getx () x) (setq x 1) (let ((x 2)) (getx)) ⇒ 2
Now, the result of (getx)
is 2
! That’s because under
dynamic binding, when executing getx
, the current binding for
x
at the top of our stack is the one from our let
binding. This time, getx
doesn’t see the global value for
x
, since its binding is below the one from our let
expression in the stack of bindings.
(Some variables are also “special”, and they are always dynamically
bound even when lexical-binding
is t
. See Initializing a Variable with defvar
.)