【问题标题】:Providing settable global vars提供可设置的全局变量
【发布时间】:2011-07-17 13:02:39
【问题描述】:

我需要为我的用户提供可设置的变量,例如 clojure AFAIK 提供的 warn-on-reflection,它们没有在 clojure 端定义,这就是我们可以设置它们的原因。

问题是我的 vars(所有配置内容)在很多紧密循环中使用,这就是为什么我不想让它们成为 refs,因为它们可能会在应用程序启动时设置,并且在运行时不会改变,它们会可能会被阅读数百万次,因此将它们作为参考似乎是在浪费资源。

所以问题是我可以在我的情况下定义可设置的变量吗?

【问题讨论】:

  • 不能使用 def 有什么原因吗?
  • 我已经使用了def,我需要更改一个defed var
  • 你考虑过使用“绑定”吗?
  • 是的,强制用户绑定每个配置变量并不是真正的解决方案。

标签: clojure


【解决方案1】:

如果您希望可设置的全局状态具有低开销且对所有线程可见并且不需要任何 STM 事务来控制突变,我建议只使用原子:

(def some-global-value (atom 1))

对原子的读写非常低开销。

【讨论】:

    【解决方案2】:

    warn-on-reflection 只是一个 var,尽管它是在 Clojure 的 Java 代码中而不是在 core.clj 中定义的。然而,除了定义的地方,warn-on-reflection 并没有什么特别之处;它的行为与任何其他 var 完全一样。

    如果您不想使用 var,您可能需要从“必须使用全局变量”以外的不同角度来处理您的问题。在函数式编程中,将所有必要的值传递给函数而不是依赖于全局变量是很常见的。也许是时候考虑这种方法了。

    【讨论】:

    • 它是一个内置的 var,这意味着它没有在 core.clj 中定义,而是在 java 代码中,这意味着它没有在 clojure 中定义。
    • 我很抱歉误解了您所说的“未在 Clojure 中定义”的意思。无论如何,我的主要观点是:warn-on-reflection 是一个 var,除了在 Java 代码中定义之外,它的行为与任何其他 var 一样。没有“具有特殊能力的变量”的概念。
    • 它有点像一个特殊的变量,你可以设置!它。当您使用 say def 定义 var 时,您无法设置!它,但你可以设置!反思警告。
    • 目前,尝试使用 set! 设置 var 的根绑定是错误的,即 var 分配是线程本地的。 Clojure java 代码使用线程绑定定义 warn-on-reflection。同样,如果您使用“绑定”定义变量,则可以使用“设置!”。没有“具有特殊能力的变量”的概念。
    【解决方案3】:

    您可以使用let 创建本地绑定,这样参数可以是动态的,您仍然可以快速访问。唯一的问题是,如果有人在循环运行时更改了参数,则循环不会接收到该参数(无论如何,IMO 这应该是所需的行为)。

    【讨论】:

    • let 仅适用于 let 块中的代码,我正在寻找类似warn-on-reflection 的设置,它会影响整个库而不仅仅是一个代码块。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-18
    • 2020-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多