【问题标题】:When does clojure remove a variable?clojure 什么时候删除变量?
【发布时间】:2017-02-05 16:15:08
【问题描述】:

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

我意识到memoize 返回一个函数,但是为了存储状态,它使用了一个本地“变量”mem。但是 after memoize 返回函数,外部 let 不应该从作用域中消失。函数怎么还能引用mem

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

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

【问题讨论】:

  • @Flimzy,感谢您的称赞:D

标签: variables clojure scope memoization


【解决方案1】:

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

但是在 memoize 返回函数之后,外部 let 不应该从作用域中消失。函数怎么还能引用mem呢。

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

假设,我创建了另一个 memoized 函数,然后 memoize 使用了另一个 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 指的是每个返回函数中的不同原子。

【讨论】:

猜你喜欢
  • 2014-10-06
  • 2010-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多