阅读最近的一个问题,我确定了正在讨论的功能
(def fib-seq
(lazy-cat [0 1] (map + (rest fib-seq) fib-seq)))
Run Code Online (Sandbox Code Playgroud)
虽然抓住了一个序列的头部,但是我想到了重新阅读我的答案,我已经掩盖了细节,就像他们很明显一样,所以我回过头来澄清并且做得很短.我知道fib-seq是一个var,只要它在它周围就能保存序列中的所有元素,但我根本不清楚序列是如何被保持的确切机制.任何澄清将不胜感激.
Mic*_*zyk 12
基本上,常规GC规则适用...序列只是一个对象并且保持在其头部意味着保持对该对象的引用.这需要保留已经在内存中实现的尽可能多的序列,因为Clojure序列是高速缓存的.
(更详细的解释如下 - 请参阅粗体片段以获取它的要点...... ;-))
Clojure中的"序列"是实现ISeq接口的对象.这提供了提取序列的第一个元素和序列的其余部分(实现ISeq的另一个对象)的方法.作为一个关键细节,这些不仅关注计算正确的对象(序列的第一个/其余部分)并将其返回给调用者,而且还要将计算值缓存在内存中,以便后续请求更快 - 而且更多重要的是,所有对序列的相同元素的所有请求都保证返回相同的值,即使ISeq是在可变Java对象之上生成的,该对象在某个时刻发生了变化.(注意这对Clojure序列的不可变语义绝对至关重要.)
另一方面,Var是一个容器,它粗略地保存了一些Java对象的"指针".如果这恰好是一个ISeq,那么只要Var本身不是垃圾收集的(如果它是当前现有命名空间中的顶级var,它显然不会是这样)或反弹,那么ISeq本身就不会是垃圾收集,特别是,它将用于缓存第一个/其余序列的内存不会被释放.
至于序列的其他元素:绑定到Var的ISeq的"rest"是一个ISeq本身.此外,它由第一个ISeq缓存.因此,绑定到Var的ISeq的"rest"ISeq的第一个元素永远不会被垃圾收集,因为对它的引用由绑定到Var的ISeq的"rest"ISeq持有,而这个ISeq不会是GC'd,因为它被ISeq缓存为'rest'组件被绑定到Var,只要它被绑定到Var,它反过来就不会是GC,而var通常永远不会GC'd,因为它是命名空间中的顶级Var.
很明显,如果它的名称空间()或名称空间本身被抛出(),它将被GC保留.如果它恰好持有了一个ISeq,那么当且仅当它不被其他一些代码保存时,该ISeq将被GC化 - 当然通常的GC规则适用.对于引入的绑定和引入的本地绑定,以上所有内容都适用于绑定的模数生命周期问题.(这不是本Q的主题.)ns-unmap
remove-ns
binding
let
归档时间: |
|
查看次数: |
1758 次 |
最近记录: |