clojure何时删除变量?

Mri*_*ury 0 variables scope clojure memoization

我正在寻找源头memoize.来自C++/Python等语言,这部分让我很难受: (let [mem (atom {})] (fn [& args] (if-let [e (find @mem args)] ...

我意识到memoize返回一个函数,但是对于存储状态,它使用本地"变量" mem.但是 memoize返回函数之后,不应该从范围消失那个外部.该功能如何仍然可以参考mem.

为什么Clojure不删除该外部变量,以及它如何管理变量名称.就像假设一样,我制作另一个memoized函数,然后memoize使用另一个mem.这个名字与之前的名字没有冲突mem吗?

PS:我当时认为那里肯定会发生一些事情,这会阻止这种情况发生,所以我给自己写了一个更简单的版本,就像http://ideone.com/VZLsJp一样,但仍然有点像memoize.

Mag*_*gos 5

如果没有线程可以访问它们,对象是垃圾收集的,就像通常的JVM语言一样.如果一个线程具有对返回memoize的函数的引用,并且该函数具有对原子的引用,mem那么传递原子仍然是可访问的.

但是memoize返回函数后,不应该从范围消失那个外部.该功能如何仍然参考mem.

这就是所谓的闭包.如果使用其环境中的名称定义函数,则之后将保留对该值的引用 - 即使定义环境已消失且函数是唯一可以访问的函数.

就像假设,我制作另一个memoized函数,然后memoize使用另一个mem.这个名字与之前的记忆没有冲突吗?

不,除非可能让程序员感到困惑.具有多个范围,每个范围都声明自己的名称mem是非常可能的,并且通常使用词法范围规则来确定何时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. 
Run Code Online (Sandbox Code Playgroud)

但一般来说这个想法很简单 - 名称的值是程序文本中最接近它的地方的定义 - 在本地范围内或在最近的外部范围内.不同的调用memoize创建不同的闭包,以便名称mem引用每个返回函数中的不同原子.