Example of Lexical vs. Dynamic Binding

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.)