2011-12-09 35 views
4

memoize是否跟蹤綁定的更改,以便返回它存儲的計算不正確?memoize如何與Clojure中的綁定進行交互?

例如,如果我有一個函數foo如:

(defn foo [bar baz] 
... 
    (let [config-val *config-val*] 
    ...) 
) 

我包含內的結合,所以我可以改變的*config-val*值,並memoizing它意味着如果我改變的*config-val*值,但不是參數它不會重新計算函數的值?相反,它會給我與舊配置功能的價值?

回答

4

在Clojure 1.3.0 memoize沒有跟蹤重新綁定。

user=> (def ^:dynamic *x* 5) 
#'user/*x* 
user=> (def f (memoize #(+ *x* %))) 
#'user/f 
user=> (f 1) 
6 
user=> (binding [*x* 6] (f 1)) 
6 
user=> (binding [*x* 7] (f 1)) 
6 

此外,

user=> (binding [*x* 7] (f 3)) 
10 
user=> (f 3) 
10 
user=> *x* 
5 
2

memoize不佔結合,這可以通過查看在其中的原子地圖僅由參數鍵控源來確認。實際上,動態重新綁定的功能不是「引用透明」的(即不能用其值替代)。

是否有什麼能夠阻止您將*config-val*作爲參數傳遞,至少是您想要記憶的函數?


user=> (source memoize) 
(defn memoize 
    "Returns a memoized version of a referentially transparent function. The 
    memoized version of the function keeps a cache of the mapping from arguments 
    to results and, when calls with the same arguments are repeated often, has 
    higher performance at the expense of higher memory use." 
    {:added "1.0"} 
    [f] 
    (let [mem (atom {})] 
    (fn [& args] 
     (if-let [e (find @mem args)] 
     (val e) 
     (let [ret (apply f args)] 
      (swap! mem assoc args ret) 
      ret))))) 
+0

不是真的我只是試圖找出方法來重組這個,我已經得到了一些很好的工作代碼,我只是想辦法讓它快很多。 – toofarsideways

2

作爲documentation for memoize所暗示的,一個memoized功能將保持的參數的映射的一個內部高速緩存到的結果。當使用參數調用memoized函數時,它已經看到它不會做任何事情,而是從緩存中查找正確的返回值。沒有什麼會被重新計算,你會得到與你最後一次調用函數相同的結果。任何rebindings將被忽略。

user=> (def ^:dynamic op +) 
user=> (defn add [x y] (op x y)) 
user=> (add 1 2) 
3 
user=> (binding [op -] 
     (add 1 2)) 
-1 
user=> (alter-var-root #'add memoize) 
user=> (add 1 2) 
3 
user=> (binding [op -] 
     (add 1 2)) 
3 
相關問題