Sequence vs LazyList

时间:2012-02-08 21:05:32

标签: data-structures f# sequence lazy-evaluation

我无法理解序列与LazyList之间的差异。他们既懒惰又可能无限。虽然来自.NET框架的seq<'T>IEnumerable<'T>,但F# PowerPack中包含LazyList。在实践中,我遇到的序列比LazyList s更频繁。

他们在性能,使用情况,可读性等方面有何不同?与LazyList相比,seq声誉差的原因是什么?

2 个答案:

答案 0 :(得分:31)

LazyList只计算每个元素一次,无论遍历列表的次数如何。通过这种方式,它更接近于从Seq.cache返回的序列(而不是典型的序列)。但是,除了缓存之外,LazyList的行为与列表完全相同:它使用了引擎盖下的列表结构并支持模式匹配。所以你可能会说:当你需要列表语义和缓存(除了懒惰)之外,使用LazyList而不是seq

对于两者都是无限的,seq的内存使用是恒定的,而LazyList是线性的。

这些docs可能值得一读。

答案 1 :(得分:19)

除了Daniel的答案之外,我认为主要的实际区别在于您如何处理LazyListseq结构(或计算)。

  • 如果要处理LazyList,通常会使用模式匹配编写递归函数(非常类似于处理普通的F#列表)

  • 如果要处理seq,可以使用内置函数,也可以编写调用GetEnumerator的命令式代码,然后在循环中使用返回的枚举器(可以写成递归函数,但它会改变枚举器)。你不能使用通常的头/尾样式(使用Seq.tailSeq.head),因为这样效率极低 - 因为seq不保留评估的元素和{{1}的结果需要从一开始就重新进行迭代。

关于Seq.headseq的声誉,我认为F#库设计采用务实的方法 - 因为LazyList实际上是.NET seq,所以非常方便用于.NET编程(它也很好,因为您可以将其他集合视为IEnumerable)。懒惰列表不是那么频繁,因此在大多数情况下,正常的F#列表和seq就足够了。