使用闭包代替全局变量 [英] Using a Closure instead of a Global Variable

查看:177
本文介绍了使用闭包代替全局变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题是使用局部特殊变量上有关最佳效果的注释的延续。避免全局变量。据我了解,全局变量存在问题,主要是因为它们有可能干扰参照透明性。如果表达式使用其调用上下文之外的信息来更改全局值(例如,全局变量本身的先前值或任何其他外部值),则将违反透明性。在这些情况下,评估表达式在不同时间可能有不同的结果,无论是返回的值还是副作用。 (但是,似乎并不是所有的全局更新都是有问题的,因为某些更新可能不依赖于任何外部信息,例如,将全局计数器重置为0)。深度嵌入计数器的常规全局方法可能如下所示:

This question is a continuation of the comments at Using Local Special Variables, regarding how best to avoid global variables. As I understand it, global variables are problematic mainly because they have the potential to interfere with referential transparency. Transparency is violated if an expression changes a global value using information outside its calling context (eg, a previous value of the global variable itself, or any other external values). In these cases evaluating the expression may have different results at different times, either in the value(s) returned or in side effects. (However, it seems not all global updates are problematic, since some updates may not depend on any external information--eg, resetting a global counter to 0). The normal global approach for a deeply embedded counter might look like:

* (defparameter *x* 0)
*X*
* (defun foo ()
    (incf *x*))
FOO
* (defun bar ()
    (foo))
BAR
* (bar)
1
* *x*
1

这似乎违反了参照透明性,因为(incf * x *)取决于 * x的外部(全局)值* 来完成其工作。以下是通过消除全局变量来维持功能和引用透明性的尝试,但我不相信它确实如此:

This would seem to violate referential transparency because (incf *x*) depends on the external (global) value of *x* to do its work. The following is an attempt to maintain both functionality and referential transparency by eliminating the global variable, but I'm not convinced that it really does:

* (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)有一个(潜在的)副作用,并且每次调用它都会返回不同的(但未使用的)值。这是否确认对有关变量使用闭包不能解决透明性问题?

The global variable is now gone, but it still seems like the expression (inc-x) has a (latent) side effect, and it will return different (but unused) values each time it is called. Does this confirm that using a closure on the variable in question does not solve the transparency problem?

推荐答案


全局变量之所以成问题,主要是因为它们有可能干扰参照透明性

global variables are problematic mainly because they have the potential to interfere with referential transparency

如果要创建全局配置值,则

If one wants to create a global configuration value, a global variable in Common Lisp is just fine.

通常,最好打包一堆配置状态,然后将其放入对象中可能会更好。

Often it's desirable to package a bunch of configuration state and then it may be better to put that into an object.

没有普遍要求使程序具有引用透明性

There is no general requirement for procedures to be referential transparent.

对指导很有用按照软件工程原理进行软件设计,但通常,比严格的原则更容易调试和维护。

It's useful to guide software design by software engineering principles, but often easy debugging and maintenance is more important than strict principles.

(let ((x 0))
  (defun inc-x () (incf x))
  (defun reset-x () (setf x 0))
  (defun get-x () x))

实际上上面的意思是


  • 难以检查

  • 具有重新加载代码的问题

  • 禁止文件编译器识别函数的顶级性质

  • 创建一个仅用于管理文件的完整API单个变量

  • is difficult to inspect
  • has problematic effects of reloading the code
  • prohibits the file compiler to recognize the top-level nature of the functions
  • creates a whole API for just managing a single variable

这篇关于使用闭包代替全局变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆