如何在绑定阴影时调用原始函数?

时间:2013-01-31 15:07:01

标签: clojure functional-programming

我有这种情况:

 (defn a []
   (do-something))

 (defn b []
   (let [original (a)]
      (modify-original)))

 (defn c []
   (binding a b)
     (a))

如何“破解绑定”并在a中呼叫b?我认为闭包可以处理这种情况所以我写了类似的东西,但它不起作用:

 (defn c []
   (let [original-a a
         b (fn [] 
             (let [original (original-a)]
               (modify-original)))]
     (b)))

哦,我差点忘了:代码要复杂得多,因为c没有直接调用b。它被称为它的子功能,我无法改变。这就是为什么我不能使用类似的东西:

(defn ^:dynamic state [] (something))

2 个答案:

答案 0 :(得分:4)

如果您希望始终使用函数ab的原始值,则可以将原始a“抓取”到函数b的环境中(闭包) ):

(defn ^:dynamic a []
  (do-something))

(def b (let [a a]
         (fn []
           (let [original (a)]
             (modify-original)))))

(defn c []
  (binding [a b]
    (a)))

<强>更新即可。或

(let [a a] (defn b []
             (let [original (a)]
               (modify-original))))

答案 1 :(得分:1)

你可以使用java线程来“透视”绑定,方法是创建并从未绑定的线程中获取var的值,并将其保留在var / atom /中ref / etc由它所绑定的线程上的代码找到:

user> (defn c [] 
        (let [tmp-atom (atom nil) 
              original-a (do (doto (Thread. #(reset! tmp-atom a)) .start .join) 
                             @tmp-atom)] 
          {:local-a a :original-a original-a}))
user> (c)
{:local-a 4, :original-a 4}
user> (binding [a 7] (c))
{:local-a 7, :original-a 4}                                    

或者对于较小的示例,首先定义一些共享状态和一个要绑定的var

user> (def result (atom ""))
#'user/result
user> (def ^:dynamic a 4)
#'user/a

在没有绑定的线程上捕获a,它将获得a:

的根值
user> (binding [a 5] (.start (Thread. #(reset! result  (str "a was " a)))))
#<Thread Thread[Thread-77,5,main]>
user> result
#<Atom@7c75031f: "a was 4">

然后将其与运行相同代码进行比较,而不使用使用a的绑定值的线程:

user> (binding [a 5] (reset! result  (str "a was " a)))
"a was 5" 
user> result
#<Atom@7c75031f: "a was 5">
user>

大多数(全部?)正常的Clojure并发工具都小心地将绑定推送到新线程以防止这样的情况

<小时/> 把它们放在一起: