请在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中,因为它并不是你应该在一般情况下做的事情,如这个回答所解释的。编译后发生变化的州态应属于保护性资源,如原子,并且更新语义是一个纯函数,将旧.setState()转换为新 staat(对于原子而言,它使用`swap!`)。
...