Clojure中函数的动态绑定

时间:2012-12-01 13:31:23

标签: binding clojure

我有一个算法,它在工作期间使用了许多不同的功能或步骤。我想运行具有绑定到这些步骤的不同可能功能的算法。本质上,我想准备一些值集(特定的函数应该绑定到这个特定的步骤)并运行我的算法与每个集合。并且用输入集捕获每次运行的结果。

类似的东西:

(binding [step1 f1
          step2 f2]
(do-my-job))

(binding [step1 f11
          step2 f22]
(do-my-job))

但使用动态绑定表达式。

我有什么选择?

4 个答案:

答案 0 :(得分:2)

所以你试图做一些像参数扫描的事情?

我看不出你为什么需要动态绑定。您的算法是根据第一类函数调用定义的。只需将函数作为参数传递给算法。

要尝试所有值,只需生成值的排列,然后在此列表上运行map。您将从中获得所有结果。

答案 1 :(得分:1)

因为绑定是一个宏,你需要编写一个生成动态绑定表单的宏。

答案 2 :(得分:0)

好吧,看来我的工作方式如下:

(def conditions [[`step1 f1 `step2 f2] [`step1 f11 `step2 f22]])

(map #(eval `(binding ~% body)) conditions)

答案 3 :(得分:0)

所以,我已经对此进行了测试,据我所知,这一切都正常。

在下面的示例中,我创建了一个var,然后将此var重新绑定到一个函数。 正如您所看到的,对函数的调用发生在词法范围之外 绑定表单,所以我们在这里有动态绑定。

(def
  ^{:dynamic true}
  *bnd-fn*
  nil
  )

(defn fn1 []
  (println "fn1"))

(defn fn2 []
  (println "fn2"))


(defn callfn []
  (*bnd-fn*))

;; crash with NPE
(callfn)

;; prints fn1
(binding [*bnd-fn* fn1]
  (callfn))

;; prints fn2
(binding [*bnd-fn* fn2]
  (callfn))

我一直在使用类似的方法来创建我自己的库(Clojure-owl,如果你感兴趣的话!),虽然在我的情况下我动态重新绑定的东西是一个Java对象。

在这种情况下,虽然我允许动态重新绑定,但在大多数情况下我没有;我只是为不同的名称空间使用不同的java对象。这对我很有用。

在回复您的评论时,如果您想要一个绑定表单,那么这很容易实现。添加以下代码。

(defn dobinding [fn]
  (binding [*bnd-fn* fn]
    (callfn)))

(dorun
 (map dobinding
             [fn1 fn2]))

函数dobinding运行所有其他函数。然后我用一张地图评估这个(和dorun或你得到一个懒的序列)。这为每个步骤运行两个函数。显然,您需要传递一个列表列表。如果您愿意,您应该可以并行化整个列表。

这比尝试拼接整个矢量要容易得多。评估绑定表单中的值,以便它可以是您喜欢的任何内容。