eval表单应该在null词法环境中评估给定的表单,我没有得到我期望的结果

时间:2012-07-24 18:10:39

标签: common-lisp

假设我有一个特殊的var:

(defvar x 20)

然后我执行以下操作:

(let ((x 1)) (eval '(+ x 1))

,评估为2。

根据CLHS,eval“评估当前动态环境和零词汇环境中的形式”。所以,我希望得到21而不是2。

我错过了什么吗?

现在,如果我没有符号y的动态绑定,则评估

(let ((y 1)) (eval '(+ y 1))

我得到条件:“变量Y是未绑定的”,这是有道理的,因为y没有动态绑定。

注意:我正在使用SBCL 1.0.57

提前感谢您的帮助!

2 个答案:

答案 0 :(得分:7)

示例x中的

special,这意味着它绑定在动态环境中

y 特殊,因此它被绑定在词汇环境中


所以在第一个eval时,环境可以这样表示:

dynamic environment:  { x : 1 } -> { x : 20, ...other global variables... } -> nil
lexical environment:  nil

符号x很特殊,因此eval当前动态中查找x 环境并找到x = 1


假设它与上一个示例在同一个lisp中运行,第二个eval的环境如下所示:

dynamic environment: { x : 20,  ...other global variables... } -> nil
lexical environment: { y :  1 } -> nil

符号y 特殊,因此eval null 中查找y 词汇环境 - 当前的词汇环境 - 什么也没发现。

当你意识到通常编译lisp和词法时,这是有道理的 在某些情况下,环境可以优化为简单的mov指令。

答案 1 :(得分:5)

DEFVAR声明其变量特殊。在全球范围内,无处不在。你也不能轻易删除它。

这也是你永远不应该使用xilist等常用名称作为DEFVAR的变量名称的原因。请确保使用*x**i**list*代替。否则,具有这些通用名称的所有变量(甚至是本地变量)都被声明为特殊。