Here’s a simpler explanation of the scoping test I gave in my first post.
We define a function f which uses a free variable, lex. The value of lex is defined as t by the enclosing environment:
(let ((lex t)) (defvar f (lambda () (if lex "Lexical" "Dynamic"))))
(I’ve changed the return values to strings to avoid confusion.)
Calling (f) returns the value “Lexical”:
> (f)
"Lexical"
Now we call f in an environment where lex has a different value, nil:
(let ((lex nil)) (f))
The question is, which value of lex should f now use?
With Dynamic Scoping f uses the value lex has when the function is called.
With Lexical Scoping f uses the value lex had when the function was defined.
Dynamic Scoping is sometimes useful; for example, if lex was a flag that controlled debugging output you could set it to nil to turn off debugging after the function was defined.
However, the consensus is that Lexical Scoping is preferred because it avoids obscure bugs due to the inadvertent reuse of variable names. For example, suppose we defined a function test using a parameter lex, forgetting that f uses lex:
(defun test (lex) (print lex) (f))
Now, in a Lisp with Dynamic Scoping, calling (test nil) changes the behaviour of f:
> (test nil)
nil
"Dynamic"
Note that if you want to try these examples on a Lisp with separate namespaces for variables and functions, like Common Lisp, change the calls to (f) in the above examples to:
(funcall f)