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

但实际上,因为 var 是全局的,您应该偏好使用其他机制来保存状态,要么在周围传递一个有状态的引用(比如一个 atom),或者在一些相对罕见的情况下,在一个 var 中放置一个有状态的引用(但按我个人的观点,最好不要这么做,最好为 0)。

是的,这不是在 clojure.core 中,因为正如这个回答所解释的,这不是您应该一般做的事。编译后改变的状态应该属于像 atom 这样的受保护的结构,并且更新语义是一个纯函数,它将旧状态转换为新状态(对于 atom,使用 `swap!`)。
...