何时使用F#中的序列而不是列表?

dod*_*der 75 f# list

我知道列表实际上包含值,序列是别名IEnumerable<T>.在实际的F#开发中,我何时应该使用序列而不是列表?

以下是我可以看到序列更好的原因:

  • 与其他需要的.NET语言或库交互时 IEnumerable<T>.
  • 需要表示无限序列(在实践中可能不是很有用).
  • 需要懒惰的评价.

还有其他人吗?

Tom*_*cek 87

我认为您选择何时选择的摘要Seq非常好.以下是一些额外的观点:

  • Seq在编写函数时默认使用,因为它们适用于任何.NET集合
  • Seq如果您需要Seq.windowed或等高级功能,请使用Seq.pairwise

我认为Seq默认情况下选择是最好的选择,所以我什么时候选择不同的类型呢?

  • 使用List时,您使用需要递归处理head::tail模式
    (实现一些功能,不提供标准库)

  • List当您需要一个可以逐步构建的简单不可变数据结构时使用
    (例如,如果您需要在一个线程上处理列表 - 显示一些统计信息 - 并在您收到时同时继续在另一个线程上构建列表更多价值,即来自网络服务)

  • 在使用List短列表时使用 - 如果值通常表示空列表,则列表是最佳数据结构,因为它在该场景中非常有效

  • Array在需要大量值类型集合时使用
    (数组将数据存储在平坦内存块中,因此在这种情况下它们的内存效率更高)

  • 使用Array时,你需要随机存取或更高的性能(和缓存局部性)

  • *"当您需要一个简单的**不可变数据结构**时,可以使用`List` [...],您可以逐步构建[...]并同时**继续在另一个线程上构建列表**[...]"*你能详细说明你的意思吗/它是如何运作的?谢谢. (3认同)
  • @Noein这个想法是你总是可以遍历列表(它们是不可变的),但是你可以使用`x :: xs`创建新的列表,而不会破坏任何可能正在迭代`xs'的现有worker. (2认同)

Jon*_*rop 27

也喜欢以下seq时间:

  • 您不希望同时将所有元素保存在内存中.

  • 表现并不重要.

  • 您需要在枚举之前和之后执行某些操作,例如连接到数据库并关闭连接.

  • 你没有连接(重复Seq.append将堆栈溢出).

喜欢的list时间:

  • 元素很少.

  • 你会在前期和斩首很多.

无论是seq也不list是良好的并行性,但这并不一定意味着他们是坏的.例如,您可以使用任意一个来表示要并行完成的一小组单独的工作项.

  • @Dr_Asik数组是最好的,因为你可以递归细分它们并保留良好的引用局部性.树木是最好的,因为你也可以细分它们,但参考地点不是那么好.列表和序列很糟糕,因为您无法细分它们.如果您使用备用元素,那么您将获得最差的引用位置.Guy Steele讨论了阻碍并行性的线性集合,尽管他只考虑工作和深度而不考虑局部性(aka*cache complexity*).http://labs.oracle.com/projects/plrg/Publications/ICFPAugust2009Steele.pdf (4认同)

pad*_*pad 11

只有一点:Seq并且ArrayList并行性要好.

您有几种选择:PSEQ从F#PowerPack中,Array.Parallel模块和Async.Parallel(异步计算).由于其顺序性(head::tail组合),列表对并行执行来说很糟糕.


Rm5*_*558 7

列表更实用,数学友好.当每个元素相等时,2个列表相等.

序列不是.

let list1 =  [1..3]
let list2 =  [1..3]
printfn "equal lists? %b" (list1=list2)

let seq1 = seq {1..3}
let seq2 = seq {1..3}
printfn "equal seqs? %b" (seq1=seq2)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


Ale*_*ček 5

您应该始终Seq在公共API中公开。在您的内部实现中使用ListArray