序列与 LazyList

发布于 2025-01-03 23:00:56 字数 355 浏览 1 评论 0原文

我无法理解序列和 LazyList 之间的差异。他们都很懒惰,而且潜力无限。虽然 seq<'T> 是 .NET 框架中的 IEnumerable<'T>,但 LazyList 包含在 F# PowerPack。在实践中,我遇到的序列比 LazyList 更频繁。

它们在性能、使用、可读性等方面有何差异?与 seq 相比,LazyList 的声誉如此差的原因是什么?

I can't wrap my head around the differences between sequence and LazyList. They're both lazy and potentially infinite. While seq<'T> is IEnumerable<'T> from .NET framework, LazyList is included in F# PowerPack. In practice, I encounter sequences much more often than LazyLists.

What are their differences in terms of performance, usage, readability, etc? What are reasons for such a bad reputation of LazyList compared to that of seq?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小ぇ时光︴ 2025-01-10 23:00:56

无论遍历列表多少次,LazyList 都只计算每个元素一次。这样,它更接近于从 Seq.cache 返回的序列(而不是典型的序列)。但是,除了缓存之外,LazyList 的行为与列表完全相同:它在底层使用列表结构并支持模式匹配。因此,您可能会说:当您需要列表语义和缓存(除了惰性之外)时,请使用 LazyList 而不是 seq

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

这些文档可能值得一读。

LazyList computes each element only once regardless of how many times the list is traversed. In this way, it's closer to a sequence returned from Seq.cache (rather than a typical sequence). But, other than caching, LazyList behaves exactly like a list: it uses a list structure under the hood and supports pattern matching. So you might say: use LazyList instead of seq when you need list semantics and caching (in addition to laziness).

Regarding both being infinite, seq's memory usage is constant while LazyList's is linear.

These docs may be worth a read.

白色秋天 2025-01-10 23:00:56

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

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

  • 如果您想处理 seq,您可以使用内置函数或者你必须写命令式调用 GetEnumerator 的代码,然后在循环中使用返回的枚举器(可以编写为递归函数,但它会改变枚举器)。您不能使用通常的头/尾样式(使用 Seq.tailSeq.head),因为那效率极低 - 因为 seq 确实不保留求值的元素,Seq.head的结果需要从头开始重新迭代。

关于 seq 和 LazyList 的声誉,我认为 F# 库设计采取了务实的方法 - 因为 seq 实际上是 .NET IEnumerable ,对于 .NET 编程来说非常方便(而且它也很好,因为您可以将其他集合视为 seq)。惰性列表并不常见,因此普通的 F# 列表和 seq 在大多数情况下就足够了。

In addition to Daniel's answer, I think the main practical difference is how you process the LazyList or seq structures (or computations).

  • If you want to process LazyList, you would typically write a recursive function using pattern matching (quite similar to processing of normal F# lists)

  • If you want to process seq, you can either use built-in functions or you have to write imperative code that calls GetEnumerator and then uses the returned enumerator in a loop (which may be written as a recursive function, but it will mutate the enumerator). You cannot use the usual head/tail style (using Seq.tail and Seq.head), because that is extremely inefficient - because seq does not keep the evaluated elements and the result of Seq.head needs to re-iterate from the start.

Regarding the reputation of seq and LazyList, I think that F# library design takes a pragmatic approach - since seq is actually .NET IEnumerable, it is quite convenient for .NET programming (and it is also nice because you can treat other collections as seq). Lazy lists are not as frequent and so normal F# list and seq are sufficient in most of the scenarios.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文