这个问题是使用局部特殊变量的注释的继续,关于如何最好地避免全局变量。据我了解,全局变量存在问题,主要是因为它们有可能干扰参照透明性。如果表达式使用其调用上下文之外的信息来更改全局值(例如,全局变量本身的先前值或任何其他外部值),则会违反透明度。在这些情况下,评估表达式在不同时间可能有不同的结果,无论是返回的值还是副作用。(但是,似乎并不是所有的全局更新都是有问题的,因为某些更新可能不依赖于任何外部信息,例如,将全局计数器重置为0)。深度嵌入计数器的常规全局方法可能类似于:
* (defparameter *x* 0)
*X*
* (defun foo ()
(incf *x*))
FOO
* (defun bar ()
(foo))
BAR
* (bar)
1
* *x*
1
Run Code Online (Sandbox Code Playgroud)
这似乎违反了参照透明性,因为它(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
Run Code Online (Sandbox Code Playgroud)
全局变量现在已经消失了,但是表达式似乎仍然(inc-x)具有(潜在的)副作用,并且每次调用它都会返回不同的(但未使用的)值。这是否确认对有关变量使用闭包不能解决透明性问题?