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这样是否有问题?

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

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)。

但是,实际上,因为变量是全局的,你应该优先考虑使用其他机制来持有状态,要么传递一个有状态的引用(如原子原子),要么在相对罕见的情况下,将一个有状态的引用放在变量中(但在我看来越少越好,理想情况下为0)。

是的,这不是在clojure.core中,因为它不是你应该在一般情况下做的事情,如这个答案中解释的那样。在编译后发生更改的状态真的属于像原子那样受保护的元素,并且更新语义是一个纯函数,它将旧状态转换为新状态(对于原子来说,使用`swap!`)。
...