rob*_*oby 5 clojure lazy-sequences
处理seq
I中的每个元素时,通常先使用并休息.然而,这些将导致a lazy-seq
通过调用seq
论证而失去其"懒惰" .我的解决方案是在使用s 时使用(first (take 1 coll))
和(drop 1 coll)
取而代之lazy-seq
,虽然我认为drop 1
很好,但我并不特别喜欢打电话first
和take
获取第一个元素.
有没有比较惯用的方法呢?
Mic*_*zyk 10
文档字符串说first
并且rest
说这些函数调用seq
它们的参数来传达这样的想法:seq
当你传入一个seqable集合时你不必自称为自己,而seqable集合本身并不是一个seq,比如一个向量或集合.例如,
(first [1 2 3])
;= 1
Run Code Online (Sandbox Code Playgroud)
如果first
没有呼吁seq
它的论点就行不通; 你不得不说
(first (seq [1 2 3]))
Run Code Online (Sandbox Code Playgroud)
相反,这将是不方便的.
双方take
并drop
还呼吁seq
对他们的论点,否则你不能打电话给他们上的载体和如上所述等.事实上,所有标准seq集合都是如此 - 那些不seq
直接调用的集合构建在较低级别的组件上.
这绝不会损害懒惰的seqs的懒惰.由于first
/ rest
调用而发生的强制/实现是可能获得所请求结果的最小量.(多少取决于参数的类型;如果它实际上不是懒惰的,那么first
调用中不会涉及额外的实现;如果它是部分惰性的 - 也就是说,分块 - 会有一些额外的实现(一次最多可计算32个初始元素);如果它完全是惰性的,则只计算第一个元素.)
显然first
,当传递一个懒惰的seq时,必须强制实现它的第一个元素 - 这就是重点.rest
实际上有点懒,因为它实际上并没有强制实现seq的"rest"部分(next
与之形成鲜明对比,基本上相当于(seq (rest ...))
).事实上,它确实强制第一个元素被实现,以便它可以立即跳过它是一个有意识的设计选择,它避免了懒惰的seq对象的不必要的分层并保持原始seq的头部; 你可以说(lazy-seq (rest xs))
甚至推迟这个初步的实现,代价是坚持xs
到实现懒惰的seq包装器.