Common Lisp - 词汇与动态作用域,let form,声明形式



动态与词法范围。

; 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)

在词汇上做到这一点,人们会期望以下。

  1. (a)代替func2中的a
  2. func2x调用,即值b
  3. func2还附加了a的值与(a)
  4. 所以(cons y a)的计算结果是(b a).
  5. (setq a (cons y a))) (b a).
  6. 所以func1缺点会(b a) (a).
  7. 然后x (b (b a) a)) .
  8. 最终结果(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'.   

这是怎么回事?

感谢您敏锐的眼睛。 这个例子来自一本 31 年前印刷的 Lisp 教科书,直接来自"动态与词汇范围"一章。 解释也直接出自那本书。 我猜没有检查词法范围,因为作者明确警告读者,词法范围不是在 Lisp 中完成的。 我很高兴这个问题解决了。我盯着它看了一会儿,不明白到底发生了什么。 这似乎是一个奇怪的矛盾。

最新更新