代码之家  ›  专栏  ›  技术社区  ›  TToi

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

  •  3
  • TToi  · 技术社区  · 6 年前

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

    在这里 printAreEqual () 给予 真的 , print2 () 给予 但是 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 回复  |  直到 6 年前
        1
  •  8
  •   TheQuickBrownFox    6 年前

    这个 use en = ... enumerate 功能有效地做到了这一点:

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

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

    序列枚举的细粒度控制总是很棘手,而且由于状态可变,很难为其生成辅助函数。