以下示例基于 snippet,它生成允许逐一枚举序列值的函数。
这里printAreEqual()
给出true,print2()
给出12345678910,但是print1( )
给出 0000000000。
为什么enumerate返回的函数不能返回使用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
最佳答案
enumerate
函数中的 use en = ...
有效地做到了这一点:
let enumerate (xs: seq<_>) =
let en = xs.GetEnumerator()
let f =
fun () ->
en.MoveNext() |> ignore
en.Current
en.Dispose()
f
您总是在开始使用枚举器之前对其进行处理,因此在这种情况下行为可能是未定义的,并且对于具有不同实现的两个序列为什么会得到不同的结果并不重要。
序列枚举的细粒度控制总是很棘手,而且由于状态可变,很难为其创建辅助函数。
关于F#使用GetEnumerator时无法枚举yield生成的序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47350277/