2013-01-31 26 views
3

我有这样的情况:如何通过绑定来调用原始函数?

(defn a [] 
    (do-something)) 

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

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

我如何 “破结合”,并在b调用a?我认为,关闭能处理这样的情况,所以我写了这个类似的东西,但它没有工作:

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

哦,我差点忘了:代码要复杂得多,因为c不直接调用b。它被称为它的子功能,我不能改变。这就是为什么我不能用这样的:

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

+0

为了实现这个目标,我认为“a”应该被声明为动态的。如果你真的想调用“a”的根值,那你为什么不能在绑定表单前复制a的值到另一个var,然后调用它。或者我想念你的用例? –

回答

4

如果你想一直使用的a原值在功能b正如你所说,你可以“抢”原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)))) 
+0

好的,但如果我不能改变'a'会怎么样?这是一个库函数。 –

+0

@AdamSznajder我没有改变'a'。或者你的意思是'^:dynamic'部分?没有这个,你就无法“绑定”新的价值。 – mobyte

1

您可以使用java线程创建,然后从它没有绑定一个线程抓住var值,并把它留在一个VAR /原子绑定“看穿”/REF /等,以由该线程上的代码它所绑定中找到:

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}          

或者对于较小的例子,首先定义一个位共享状态的和变种结合

上的一个线程,而不绑定

捕获一个,这将得到的根值:

user> (binding [a 5] (.start (Thread. #(reset! result (str "a was " a))))) 
#<Thread Thread[Thread-77,5,main]> 
user> result 
#<[email protected]: "a was 4"> 

然后比较,为运行相同的代码,而其中使用的绑定的值线程:

user> (binding [a 5] (reset! result (str "a was " a))) 
"a was 5" 
user> result 
#<[email protected]: "a was 5"> 
user> 

大多数(所有?)正常Clojure的并发工具小心地推绑定新的线程来防止这样的


把这个共同的情况:

相关问题