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

时间:2017-11-17 12:04:48

标签: f# sequence enumeration yield

以下示例基于snippet,它生成的函数允许逐个枚举序列值。

此处printAreEqual ()提供 true 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

1 个答案:

答案 0 :(得分:7)

use en = ...函数中的enumerate实际上是这样做的:

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

在开始使用枚举器之前,你总是处理它,所以在这种情况下行为可能是不确定的,并且为什么你得到两个具有不同实现的序列的不同结果并不重要。

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