我无法理解序列与LazyList
之间的差异。他们既懒惰又可能无限。虽然来自.NET框架的seq<'T>
为IEnumerable<'T>
,但F# PowerPack中包含LazyList
。在实践中,我遇到的序列比LazyList
s更频繁。
他们在性能,使用情况,可读性等方面有何不同?与LazyList
相比,seq
声誉差的原因是什么?
答案 0 :(得分:31)
LazyList
只计算每个元素一次,无论遍历列表的次数如何。通过这种方式,它更接近于从Seq.cache
返回的序列(而不是典型的序列)。但是,除了缓存之外,LazyList
的行为与列表完全相同:它使用了引擎盖下的列表结构并支持模式匹配。所以你可能会说:当你需要列表语义和缓存(除了懒惰)之外,使用LazyList
而不是seq
。
对于两者都是无限的,seq
的内存使用是恒定的,而LazyList
是线性的。
这些docs可能值得一读。
答案 1 :(得分:19)
除了Daniel的答案之外,我认为主要的实际区别在于您如何处理LazyList
或seq
结构(或计算)。
如果要处理LazyList
,通常会使用模式匹配编写递归函数(非常类似于处理普通的F#列表)
如果要处理seq
,可以使用内置函数,也可以编写调用GetEnumerator
的命令式代码,然后在循环中使用返回的枚举器(可以写成递归函数,但它会改变枚举器)。你不能使用通常的头/尾样式(使用Seq.tail
和Seq.head
),因为这样效率极低 - 因为seq
不保留评估的元素和{{1}的结果需要从一开始就重新进行迭代。
关于Seq.head
和seq
的声誉,我认为F#库设计采用务实的方法 - 因为LazyList
实际上是.NET seq
,所以非常方便用于.NET编程(它也很好,因为您可以将其他集合视为IEnumerable
)。懒惰列表不是那么频繁,因此在大多数情况下,正常的F#列表和seq
就足够了。