【发布时间】:2019-06-24 21:57:19
【问题描述】:
这个问题是 Using Local Special Variables 的 cmets 的延续,关于如何最好地避免全局变量。据我了解,全局变量是有问题的,主要是因为它们有可能干扰参考透明度。如果表达式使用其调用上下文之外的信息(例如,全局变量本身的先前值或任何其他外部值)来更改全局值,则违反透明度。在这些情况下,评估表达式可能会在不同的时间产生不同的结果,无论是返回的值还是副作用。 (然而,似乎并非所有全局更新都有问题,因为某些更新可能不依赖于任何外部信息——例如,将全局计数器重置为 0)。深度嵌入计数器的正常全局方法可能如下所示:
* (defparameter *x* 0)
*X*
* (defun foo ()
(incf *x*))
FOO
* (defun bar ()
(foo))
BAR
* (bar)
1
* *x*
1
这似乎违反了引用透明性,因为(incf *x*) 依赖于*x* 的外部(全局)值来完成其工作。以下是通过消除全局变量来保持功能和引用透明性的尝试,但我不相信它确实如此:
* (let ((x 0))
(defun inc-x () (incf x))
(defun reset-x () (setf x 0))
(defun get-x () x))
GET-X
* (defun bar ()
(inc-x))
BAR
* (defun foo ()
(bar))
FOO
* (get-x)
0
* (foo)
1
* (get-x)
1
全局变量现在已经消失了,但表达式(inc-x) 似乎仍然具有(潜在的)副作用,并且每次调用它都会返回不同的(但未使用的)值。这是否证实了对相关变量使用闭包并不能解决透明度问题?
【问题讨论】:
标签: closures global-variables common-lisp