抓住序列的头部 [英] Holding onto the head of a sequence

查看:26
本文介绍了抓住序列的头部的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

阅读最近的一个问题,我确定了正在讨论的功能

Reading a recent question I identified the function being discussed

(def fib-seq
    (lazy-cat [0 1] (map + (rest fib-seq) fib-seq)))

就像抓住一个序列的头部一样,但我重新阅读我的答案时突然想到我已经掩盖了细节,就像它们很明显一样,所以我回去澄清并简短.我知道 fib-seq 是一个 var 并且只要它在它周围就会保存序列中的所有元素,但是我完全不清楚序列是如何被保持的确切机制.任何澄清将不胜感激.

as holding onto the head of a sequence, but it occurred to me re-reading my answer that I had glossed over the details like they were obvious, so I went back to clarify and came up short. I know that fib-seq is a var and that as long as it's around it will hold all the elements in the sequence, but I'm not clear at all on the exact mechanics of how exactly the sequence is getting held onto. Any clarifications would be appreciated.

推荐答案

基本上,常规 GC 规则适用... 序列只是一个对象,持有它的头部意味着持有对该对象的引用.这需要在内存中保存尽可能多的序列,因为 Clojure 序列已被缓存.

Basically, regular GC rules apply... A sequence is just an object and holding onto its head means holding onto a reference to this object. This entails holding as much of the sequence as has already been realised in memory, because Clojure sequences are cached.

(下面有更详细的解释——请参阅粗体部分以了解其要点……;-))

Clojure 中的序列"是一个实现了 ISeq 接口的对象.这提供了提取序列的第一个元素和序列的其余部分(另一个实现 ISeq 的对象)的方法.作为一个关键细节,它们不仅要计算正确的对象(序列的第一个/其余部分)并将其返回给调用者,而且还要将计算出的值缓存在内存中,以便任何后续请求都更快——而且,更多重要的是,即使 ISeq 是在可变 Java 对象之上生成的,该对象在某些时候会发生变化,以便保证对序列中相同元素的所有请求都返回相同的值.(请注意,这对于 Clojure 序列的不可变语义绝对至关重要.)

'A sequence' in Clojure is an object which implements the ISeq interface. This provides methods which extract the first element of the sequence and the rest of the sequence (another object implementing ISeq). As a key detail, these take care not only of computing the correct object (first / rest of the sequence) and returning it to the caller, but also of caching the computed value in memory so any subsequent requests are faster -- and, more importantly, so that all requests for the same element of the sequence are guaranteed to return the same value, even if the ISeq is being generated on top of a mutable Java object which changes at some point. (Note this is absolutely crucial to the immutable semantics of Clojure sequences.)

另一方面,Var 是一个容器,粗略地说,它包含一个指向某个 Java 对象的指针".如果这恰好是一个 ISeq,那么只要 Var 本身不被垃圾收集(如果它是当前存在的命名空间中的顶级 var,它显然永远不会是)或反弹,ISeq 本身不会被垃圾收集,特别是它用于缓存第一/其余序列的内存不会被释放.

A Var, on the other hand, is a container which holds, in rough terms, a 'pointer' to some Java object. If this happens to be an ISeq, then as long as the Var itself is not garbage collected (which it obviously won't ever be if it's a top level var in a currently existing namespace) or rebound, the ISeq itself will not be garbage collected and, in particular, the memory it uses for caching first / rest of sequence will not be released.

至于序列的其他元素:绑定到 Var 的 ISeq 的其余部分"是 ISeq 本身.此外,它被第一个 ISeq 缓存.因此,绑定到 Var 的 ISeq 的rest" ISeq 的第一个元素永远不会被垃圾收集,因为对它的引用由绑定到 Var 的 ISeq 的rest" ISeq 持有,而这个 ISeq 不会被 GC 处理,因为它被绑定到 Var 的 ISeq 缓存为其余"组件,而只要它绑定到 Var,它就不会被 GC 处理,而后者通常永远不会被 GCGC 是因为它是命名空间中的顶级 Var.

As for the other elements of the sequence: the 'rest' of the ISeq bound to the Var is an ISeq itself. Also, it gets cached by the first ISeq. Thus the first element of the 'rest' ISeq of an ISeq bound to a Var will never be garbage collected, because a reference to it is being held by the 'rest' ISeq of the ISeq bound to the Var and this ISeq won't be GC'd because it is being cached as the 'rest' component by the ISeq bound to the Var, which in turn won't be GC'd as long as it is bound to the Var, which in turn will normally never be GC'd because it's a top-level Var in a namespace.

显然,如果 Var 不再被其命名空间 (ns-unmap) 保留或命名空间本身被丢弃 (删除-ns).如果它碰巧持有一个 ISeq,那么当且仅当它没有被其他一些代码持有时,该 ISeq 才会被 GC 处理——当然,通常的 GC 规则适用.对于由 binding 引入的绑定和由 let 引入的本地绑定,以上所有内容都适用于绑定的模生存期问题.(这不是本 Q 的主题.)

Clearly the Var will be GC'd if it ceases to be held onto by its namespace (ns-unmap) or the namespace itself gets tossed (remove-ns). If it happens to have held an ISeq, that ISeq will be GC'd if and only if it isn't being held by some other bit of code -- the usual GC rules apply, of course. For bindings introduced with binding and local bindings introduced with let, all the above applies modulo lifetime issues of the bindings. (Which are not a subject of this Q.)

这篇关于抓住序列的头部的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆