As we discussed before (see let
Prevents Confusion), when you create
local variables with let
under lexical binding, those variables
are valid only within the body of the let
expression. In other
parts of your code, they have other meanings, so if you call a
function defined elsewhere within the let
body, that function
would be unable to “see” the local variables you’ve created. (On
the other hand, if you call a function that was defined within a
let
body, that function would be able to see—and
modify—the local variables from that let
expression.)
Under dynamic binding, the rules are different: instead, when you use
let
, the local variables you’ve created are valid during
execution of the let
expression. This means that, if your
let
expression calls a function, that function can see these
local variables, regardless of where the function is defined
(including in another file entirely).
Another way to think about let
when using dynamic binding is
that every variable name has a global “stack” of bindings, and
whenever you use that variable’s name, it refers to the binding on the
top of the stack. (You can imagine this like a stack of papers on
your desk with the values written on them.) When you bind a variable
dynamically with let
, it puts the new binding you’ve specified
on the top of the stack, and then executes the let
body. Once
the let
body finishes, it takes that binding off of the stack,
revealing the one it had (if any) before the let
expression.