什么时候在 F # 中使用序列而不是列表?

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

下面是我能看到的一些序列更好的原因:

  • 当与其他.NET 语言或需要 IEnumerable<T>.
  • 需要表示一个无限序列(可能在实践中并不真正有用)。
  • 需要懒惰的评估。

还有其他人吗?

13564 次浏览

I think your summary for when to choose Seq is pretty good. Here are some additional points:

  • Use Seq by default when writing functions, because then they work with any .NET collection
  • Use Seq if you need advanced functions like Seq.windowed or Seq.pairwise

I think choosing Seq by default is the best option, so when would I choose different type?

  • Use List when you need recursive processing using the head::tail patterns
    (to implement some functionality that's not available in standard library)

  • Use List when you need a simple immutable data structure that you can build step-by-step
    (for example, if you need to process the list on one thread - to show some statistics - and concurrently continue building the list on another thread as you receive more values i.e. from a network service)

  • Use List when you work with short lists - list is the best data structure to use if the value often represents an empty list, because it is very efficient in that scenario

  • Use Array when you need large collections of value types
    (arrays store data in a flat memory block, so they are more memory efficient in this case)

  • Use Array when you need random access or more performance (and cache locality)

Just one small point: Seq and Array are better than List for parallelism.

You have several options: PSeq from F# PowerPack, Array.Parallel module and Async.Parallel (asynchronous computation). List is awful for parallel execution due to its sequential nature (head::tail composition).

Also prefer seq when:

  • You don't want to hold all elements in memory at the same time.

  • Performance is not important.

  • You need to do something before and after enumeration, e.g. connect to a database and close connection.

  • You are not concatenating (repeated Seq.append will stack overflow).

Prefer list when:

  • There are few elements.

  • You'll be prepending and decapitating a lot.

Neither seq nor list are good for parallelism but that does not necessarily mean they are bad either. For example, you could use either to represent a small bunch of separate work items to be done in parallel.

You should always expose Seq in your public APIs. Use List and Array in your internal implementations.

list is more functional, math-friendly. when each element is equal, 2 lists are equal.

sequence is not.

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)

enter image description here