2024 Clojure状态调查!中分享您的想法。

欢迎!请参阅关于页面以了解更多关于如何使用本站的信息。

0
Clojure
编辑

我一直在大量使用以下函数

 (defn set-var-root [v value]
   (alter-var-root v (constantly value)))

我在其他代码中也经常看到这种模式。如果理解正确的话,它就像是一种惯例。
为什么它不在clojure.core中呢?

这可能是一个很好的补充,如果不是,为什么呢?

我曾向clojurians slack提问,并被指出到

(.bindRoot avar value)

这是我之前不知道的。但问题再次浮现,为什么它不是公共API的一部分?使用vars这种方式有什么问题吗?

为了提供一些背景信息,我正在开发一个游戏引擎,在应用程序启动时,我会设置global vars,用于输入、图形上下文等。

https://github.com/damn/gdl/blob/main/src/gdl/game.clj#L13

(defn- load-gdx-globals []
  (set-var-root #'gdl.app/app           Gdx/app)
  (set-var-root #'gdl.files/files       Gdx/files)
  (set-var-root #'gdl.graphics/graphics Gdx/graphics)
  (set-var-root #'gdl.input/input       Gdx/input))
我现在使用`.bindRoot`,可以删除我的自定义函数`set-var-root`。

我认为这是最佳方法。
在没有公开,不可移植的实现API的情况下进行使用,老实说,这似乎是最差的方法。

1 个答案

+2

与所有引用类型一样,你应该通常通过在旧值上功能性应用一个函数转换来创建新值(即 alter-var-root)。

但是实际上,由于vars是全局的,你最好使用其他机制来持有状态,或者通过传递一个诸如atom这样的状态引用,或者在某些相对罕见的情况下将一个状态引用放入vars中(但尽量少用,最好为0)。

是的,这不在clojure.core中,因为它不是你应该在一般情况下做的事情,如这个回答所解释的。在编译后发生变化的state属于类似atom这样的受保护对象,更新语义是一个纯函数,它将旧状态转换为新状态(对于atoms,使用`swap!`)。
...