F#使用GetEnumerator时无法枚举yield生成的序列

TTo*_*Toi 3 f# enumeration yield sequence

以下示例基于一个片段,该片段生成允许逐个枚举序列值的函数.

这里printAreEqual ()给出了真实,print2 ()给出了12345678910,但print1 ()给出了0000000000.

为什么枚举返回的函数不能返回使用yield生成的序列的值?


open System.Linq

let enumerate (xs: seq<_>)  = 
    use en = xs.GetEnumerator()
    fun () ->
        en.MoveNext() |> ignore
        en.Current

let s1 = seq { for i in 1 .. 10 do yield i }
let s2 = seq { 1 .. 10 }

let f1 = s1 |> enumerate
let f2 = s2 |> enumerate

let printAreEqual () = Enumerable.SequenceEqual (s1, s2) |> printf "%b" // true
let print1 () = for i in 1 .. 10 do f1() |> printf "%i" // 0000000000
let print2 () = for i in 1 .. 10 do f2() |> printf "%i" // 12345678910
Run Code Online (Sandbox Code Playgroud)

The*_*Fox 7

use en = ...enumerate功能有效地这样做:

let enumerate (xs: seq<_>) = 
    let en = xs.GetEnumerator()
    let f =
        fun () ->
            en.MoveNext() |> ignore
            en.Current
    en.Dispose()
    f
Run Code Online (Sandbox Code Playgroud)

在开始使用它之前,你总是处理枚举器,因此在这种情况下行为可能是未定义的,并且为什么对于具有不同实现的两个序列获得不同的结果并不重要.

序列枚举的细粒度控制总是很棘手,并且由于可变状态而很难创建辅助函数.

  • @TToi枚举器是为两个序列处理的(某些`Dispose()`方法是运行的),但当你试图从中枚举时,处置的枚举器应该做什么?这个问题没有答案,两种情况下的结果可能只是由于实施而产生的巧合. (2认同)