问题描述
考虑到动态和词法绑定变量的行为,我理解下面代码中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
特殊形式创建动态绑定,但没有将变量声明为特殊封闭形式。
因此我们需要声明变量 LET
的 x
绑定是特殊的:
CL-USER 27 > (progv '(x) '(1)
(let ((x 2))
(declare (special x))
(list x (symbol-value 'x))))
(2 2)
DEFVAR
OTOH 声明它的变量是特殊的。在全球范围内,没有直接的方法可以撤消该声明。