2017-02-05 42 views
0

我正在查看memoize的來源。 從像C++/Python這樣的語言的到來,這部分打我辛苦: (let [mem (atom {})] (fn [& args] (if-let [e (find @mem args)] ...clojure什麼時候刪除變量?

我意識到memoize返回功能,但對於存儲狀態,它採用的是當地的「變量」 mem。但memoize還原函數,不應該從外部讓範圍消失。功能如何仍然可以參考mem

爲什麼Clojure不刪除該外部變量,以及它如何管理變量名稱。就像假設,我做了另一個memoized函數,然後memoize使用另一個mem。這個名字是不是與早期的mem相沖突?

P.S:我在想,一定有很多的東西可以在那裏發生的事情,是防止,所以我寫了自己是一個容易的版本,即是這樣http://ideone.com/VZLsJp,但目前仍然可以工作,如memoize

+0

@Flimzy,謝謝你的好評:D –

回答

5

如果沒有線程可以訪問它們,那麼對象是垃圾收集的,按照通常的JVM語言。如果線程引用了memoize返回的函數,並且該函數具有對mem中原子的引用,則傳遞原子仍然可以訪問。

但是memoize函數返回後,不應該從外部讓範圍消失。函數如何仍然可以引用mem。

這就是所謂的closure。如果一個函數是使用其環境中的名稱來定義的,那麼它會在後面保留對該值的引用 - 即使定義環境已經消失,並且函數是唯一可以訪問的東西。

就像假設我做了另一個memoized函數,然後memoize使用另一個mem。這個名字是不是與早期的MEM衝突?

不,可能會讓程序員混淆。有多個範圍,每個都聲明自己的名字mem是非常有可能的,並且lexical scoping的常規規則用於確定在讀取mem時的含義。有一些棘手的邊界情況,如

(let[foo 2] 
    (let[foo (fn[] foo)] ;; In the function definition, foo has the value from the outer scope 
    ;; because the second let has not yet bound the name 
    (foo))) ;; => 2. 

,但一般的想法很簡單 - 一個名稱的值是最接近的程序文本的地方所定義的,一個是使用 - 無論是在本地範圍或最接近的外部範圍。 memoize的不同調用創建不同的閉包,因此名稱mem引用每個返回函數中的不同原子。

+1

謝謝!學到新東西:在Clojure關閉。 :) –

+1

以防萬一,[Python也有關閉](http://stackoverflow.com/a/4020443/4534687)! –

相關問題