Let's say I have a special var:
(defvar x 20)
then I do the following:
(let ((x 1)) (eval '(+ x 1))
which evaluates to 2.
According to CLHS, eval "Evaluates form in the current dynamic environment and the null lexical environment". So, I would expect to get 21 instead of 2.
Am I missing something?
Now if I have no dynamic binding for symbol y, evaluating
(let ((y 1)) (eval '(+ y 1))
I get condition: "The variable Y is unbound", which makes sense, since there is no dynamic binding for y.
Note: I'm using SBCL 1.0.57
Appreciate your help in advance!
in your example x
is special
which means it is bound in the dynamic environment
y
is not special, so it is bound in the lexical environment
so at the time of the first eval
the environments could be represented like this:
dynamic environment: { x : 1 } -> { x : 20, ...other global variables... } -> nil
lexical environment: nil
the symbol x
is special so eval
looks up x
in the current dynamic
environment and finds x = 1
assuming it was run in same lisp as the last example, the environment of your second eval
looks like this:
dynamic environment: { x : 20, ...other global variables... } -> nil
lexical environment: { y : 1 } -> nil
the symbol y
is not special so eval
looks up y
in the null
lexical environment -- not the current lexical environment -- and finds nothing.
this makes sense when you realize that lisp is usually compiled, and the lexical
environment can be optimized down to simple mov
instructions in some cases.
DEFVAR
declares its variables special. Globally, everywhere. You can also not remove this easily.
That's also the reason you should never use common names like x
, i
, list
as variable names for DEFVAR
. Make sure that you use *x*
, *i*
and *list*
instead. Otherwise all variables, even local ones, with these common names are declared special.