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

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

0
Clojure
编辑

我一直使用以下函数很多

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

我还在其他代码中看到很多这种模式。如果理解正确,这就像是一种惯用语。
为什么它不在 clojure.core 中?

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

我在 clojurians slack 中发问,有人向我指出

(.bindRoot avar value)

这是我之前不知道的。但再次提出一个问题:为什么它不是公共 API 的一部分?使用 var 这种方式有什么问题吗?

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

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),要么在相对罕见的情况下将一个有状态引用放在var中(但是我认为越少越好,最好是0)。

是的,这不在clojure.core中,因为它不是你应该普遍做的事情,如本回答所述。编译后改变的状态实际上应该属于像atom这样的受保护的内容,并且更新语义是一个纯函数,该函数将旧状态转换为新状态(对于原子,使用`swap!`)。
...