`progv` 中 `symbol-value` 的行为

behavior of `symbol-value` in `progv`

考虑到动态和词法绑定变量的行为,我理解以下代码中 symbol-value 的输出(动态绑定变量 a 被词法绑定变量 a 遮蔽(解释有误,见下方编辑)):

(defvar a 1)
(let ((a 2))
  (list a (symbol-value 'a)))
 ; => (2 2)

但是当使用progv创建类似的环境时,symbol-value给出了不同的结果:

(progv '(x) '(1)
  (let ((x 2))
    (list x (symbol-value 'x))))
 ; => (2 1)

为什么 (symbol-value 'x) 在第二个例子中返回 1

接受答案的最终编辑: 在 Rainer Joswig 的回答中的整个评论中我了解到 (let ((a 2)) ... ) 不绑定词法变量,但隐藏了前者的值动态绑定。 Martin Buchmann 在评论中还指出,symbol-value 忽略了词法变量。

PROGV 特殊形式创建动态绑定,但不将变量声明为 特殊形式 用于封闭形式。

因此我们需要声明变量 xLET 绑定是特殊的:

CL-USER 27 > (progv '(x) '(1)
               (let ((x 2))
                 (declare (special x))
                 (list x (symbol-value 'x))))
(2 2)

DEFVAR OTOH 声明它的变量是特殊的。在全球范围内,没有直接的方法可以撤消该声明。