使用 Clojure 在运行时动态绑定函数

Zak*_*kum 5 binding coding-style clojure

我今天开始使用 Clojure 并偶然发现可以在运行时动态更改函数的声明。这听起来很酷,所以我用这个特性写了一小段代码。

(defn ^:dynamic state [x]
   (odd x))

(defn even [x]
  (if (= x 0)
    (println "even")
    (binding [state odd] (parity x))))

(defn odd [x]
  (if (= x 0)
    (println "odd")
    (binding [state even](parity x))))

(defn parity [x]
    (state (dec x)))
Run Code Online (Sandbox Code Playgroud)

效果很好,但由于我对 Clojure 完全陌生,我不知道这是否是
a) 干净的功能代码(因为奇怪甚至似乎有副作用?)
b) 应该在运行时更改函数的方式

我将不胜感激任何形式的建议!:) -扎库姆

Joo*_*aat 5

动态绑定的使用主要是品味问题,但有一些注意事项:

动态绑定几乎是在调用堆栈上显式传递值的快捷方式。只有少数情况下这样做是完全明显的胜利;主要是诸如“通过”不支持它们的 API 传递“全局”配置设置/参数之类的事情。

依赖动态绑定的 API 很难包装成更明确的东西,而相反的方式则容易得多(通常可以半自动完成)。

动态绑定不适用于惰性序列或在当前调用堆栈之外进行评估的任何其他内容(如其他线程)。

总而言之,我认为“更干净”的函数式解决方案是将state参数作为参数传递给parity,但参数可以通过任何一种方式进行。