我正在阅读 Peter Seibel 的《实用通用 Lisp》一书。
在第 6 章,“变量”部分,“词法变量和闭包”和“动态,又名特殊,变量”。 http://www.gigamonkeys.com/book/variables.html
我的问题是,这两个部分中的示例都显示了 (let ...) 如何影响全局变量,并且并没有真正说明动态变量和词法变量之间的区别。
我了解闭包是如何工作的,但在这个例子中我真的不明白 let 有什么特别之处:
(defvar *x* 10)
(defun foo ()
(format t "Before assignment~18tX: ~d~%" *x*)
(setf *x* (+ 1 *x*))
(format t "After assignment~18tX: ~d~%" *x*))
(defun bar ()
(foo)
(let ((*x* 20)) (foo))
(foo))
CL-USER> (foo)
Before assignment X: 10
After assignment X: 11
NIL
CL-USER> (bar)
Before assignment X: 11
After assignment X: 12
Before assignment X: 20
After assignment X: 21
Before assignment X: 12
After assignment X: 13
NIL
我觉得这里没有什么特别的。bar中的外部foo递增全局x,而被let in bar包围的foo递增阴影x。有什么大不了的?我不明白这应该如何解释词法变量和动态变量之间的区别。然而这本书仍然是这样的:
那么这是如何工作的呢?LET 怎么知道当它绑定x时它应该创建一个动态绑定而不是正常的词法绑定?它知道是因为名称已被声明为特殊的。12 使用 DEFVAR 和 DEFPARAMETER 定义的每个变量的名称都会自动声明为全局特殊的。
如果let使用“普通词法绑定”绑定x会发生什么?总而言之,动态绑定和词法绑定有什么区别?这个例子对于动态绑定有什么特别之处?