eval form supposed to evaluate a given form in a n

2019-02-16 12:37发布

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!

标签: common-lisp
2条回答
唯我独甜
2楼-- · 2019-02-16 12:51

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.

查看更多
萌系小妹纸
3楼-- · 2019-02-16 13:02

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.

查看更多
登录 后发表回答