动态与词汇范围。
; One expects lexical scope.
(let (( a '(a)))
(defun func1 (x)
(setq a (cons x (cons (func2 x) a))))
(defun func2 (y)
(setq a (cons y a))))
(func1 'b)
=> (B (B A) B A)
在词汇上做,人们会期待 以下。
(a)
替换为a
。func2
使用func2
调用x
,即值b
。func2
还附加a
与(a)
的值。(cons y a)
评估为(b a)
。(setq a (cons y a)))
是(b a)
。func1
将(b a)
与(a)
合作。x
然后被分配(b (b a) a))
。(b (b a) a)
?这是矛盾吗?让我们尝试动态版本。 ;动态范围
(defparameter a '(a))
(defun func1 (x)
(setq a (cons x (cons (func2 x) a))))
(defun func2 (y)
(setq a (cons y a)))
(func1 'b)
=>(B (B A) B A)
这是预期的,但与词法范围相同?
但完全不接受以下内容。
; This won't work.
(let (( a '(a)))
(defun func1 (x)
(declare (special a))
(setq a (cons x (cons (func2 x) a))))
(defun func2 (y)
(declare (special a))
(setq a (cons y a))))
(func1 'b)
Error: Attempt to take the value of the unbound variable `A'.
发生了什么事?
答案 0 :(得分:1)
感谢敏锐的目光。这个例子来自31年前印刷的Lisp教科书,直接出自“动态与词汇范围”一章。这个解释也直接来自那本书。我猜词法范围没有被检查,因为作者明确警告读者词汇范围没有在Lisp中完成。我很高兴这个问题得到了解决。我盯着它看了一段时间,却没有理解真正发生的事情。这似乎是一个奇怪的矛盾。