在处理 a 中的每个元素时,seq
我通常使用first和rest。然而,这些将导致 alazy-seq
通过调用seq
参数而失去其“懒惰”。我的解决方案是在使用 s 时使用(first (take 1 coll))
and(drop 1 coll)
代替它们lazy-seq
,虽然我认为drop 1
这很好,但我并不特别喜欢必须调用first
并take
获取第一个元素。
有没有更惯用的方法来做到这一点?
文档字符串 forfirst
和rest
说这些函数调用它们的参数来传达这样一种想法,即当传入一个本身不是 seq 的 seqable 集合时seq
,您不必调用自己,例如向量或集合。seq
例如,
(first [1 2 3])
;= 1
如果first
不调用seq
它的论点就行不通;你不得不说
(first (seq [1 2 3]))
相反,这将是不方便的。
两者都take
调用drop
它们seq
的参数,否则你不能像上面解释的那样在向量等上调用它们。事实上,所有标准 seq 集合都是如此——那些不seq
直接调用的集合是建立在可以调用的低级组件之上的。
这绝不会削弱惰性序列的惰性。由于first
/rest
调用而发生的强制 / 实现是获得请求结果的最小量。(多少取决于参数的类型;如果它实际上不是惰性的,则first
调用中不涉及额外的实现;如果它是部分惰性的——即分块——会有一些额外的实现(一次最多计算 32 个初始元素);如果它是完全惰性的,则只计算第一个元素。)
显然first
,当传递一个惰性序列时,必须强制实现它的第一个元素——这就是重点。rest
实际上有点懒惰,因为它实际上并不强制实现 seq 的“其余”部分(这与 形成对比next
,它基本上等同于(seq (rest ...))
)。事实上,它确实强制实现第一个元素以便它可以立即跳过它,这是一种有意识的设计选择,它避免了惰性 seq 对象的不必要分层并保持原始 seq 的头部;你甚至可以说(lazy-seq (rest xs))
推迟这个最初的实现,代价是坚持xs
到实现惰性 seq 包装器实现。