F# 无法枚举使用 GetEnumerator 时由 yield 生成的序列
F# Cannot enumerate sequence generated by yield when using GetEnumerator
以下示例基于 snippet 生成的函数,这些函数允许一一枚举序列值。
此处printAreEqual ()
给出true,print2 ()
给出12345678910,但print1 ()
给出0000000000.
为什么函数 return 不能枚举 return 使用 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
您总是在开始使用枚举器之前对其进行处理,因此在这种情况下行为可能是未定义的,并且对于具有不同实现的两个序列得到不同结果的原因并不重要。
序列枚举的细粒度控制总是很棘手,并且由于可变状态很难制作辅助函数。
以下示例基于 snippet 生成的函数,这些函数允许一一枚举序列值。
此处printAreEqual ()
给出true,print2 ()
给出12345678910,但print1 ()
给出0000000000.
为什么函数 return 不能枚举 return 使用 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
您总是在开始使用枚举器之前对其进行处理,因此在这种情况下行为可能是未定义的,并且对于具有不同实现的两个序列得到不同结果的原因并不重要。
序列枚举的细粒度控制总是很棘手,并且由于可变状态很难制作辅助函数。