2013-01-31 23 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的併發工具小心地推綁定新的線程來防止這樣的


把這個共同的情況:

相關問題