6

在处理 a 中的每个元素时,seq我通常使用firstrest。然而,这些将导致 alazy-seq通过调用seq参数而失去其“懒惰”。我的解决方案是在使用 s 时使用(first (take 1 coll))and(drop 1 coll)代替它们lazy-seq,虽然我认为drop 1这很好,但我并不特别喜欢必须调用firsttake获取第一个元素。

有没有更惯用的方法来做到这一点?

4

1 回答 1

10

文档字符串 forfirstrest说这些函数调用它们的参数来传达这样一种想法,即当传入一个本身不是 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 包装器实现。

于 2013-08-06T02:49:44.877 回答