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

标签 f# sequence enumeration yield

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

这里printAreEqual()给出trueprint2()给出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/

相关文章:

c# - JS 喜欢 C# 中的枚举

scala - 为什么这样的操作符定义在 Scala 中是可能的?

f# - 面向铁路的编程 - 函数输出不通过

f# - Uri().AbsolutePath "Unexpected symbol ' .' in binding."F#中的错误表达式

c# - 什么是线程安全 (C#)? (字符串,数组,...?)

java - 在 Java 8 中迭代枚举

.net - 在泛型函数上使用约束时 F# 类型约束不匹配

python - 字典更新序列元素 #0 的长度为 15; 2 是必需的

mysql - 在 MySQL 中选择整数范围。例如。 1,2,3,4,...,n;

arrays - 判断两个斐波那契数的邻接度