clojure什么时候删除变量?

When does clojure remove a variable?

我正在查看 memoize 的来源。 来自 C++/Python 等语言,这部分让我印象深刻: (let [mem (atom {})] (fn [& args] (if-let [e (find @mem args)] ...

我意识到 memoize returns 一个函数,但是为了存储状态,它使用了本地 "variable" mem。但是 after memoize returns 这个函数,不应该让那个外部 let 从作用域中消失。函数怎么还引用了mem.

为什么 Clojure 不删除那个外部变量,它是如何管理变量名的。假设我创建了另一个记忆函数,然后 memoize 使用另一个 mem。这个名字和之前的 mem 不冲突吗?

P.S.: 我在想一定有很多事情发生在那里,阻止了那件事,所以我给自己写了一个更简单的版本,那就是像 http://ideone.com/VZLsJp ,但仍然像 memoize.

如果没有线程可以访问对象,则对象是可回收的,这是 JVM 语言的惯例。如果一个线程引用了 memoize 返回的函数,并且该函数引用了 mem 中的原子,那么该原子仍然可以传递地访问。

But after memoize returns the function, shouldn't that outer let vanish from scope. How can the function still refer to the mem.

这就是所谓的closure。如果一个函数是使用其环境中的名称定义的,它会在之后保留对该值的引用 - 即使定义环境已经消失并且该函数是唯一可以访问的东西。

Like suppose, I make another memoized function, then memoize uses another mem. Doesn't that name clash with the earlier 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 在每个返回的函数中引用不同的原子。