Seq.map 和 Seq.mapi 优化匿名函数 returns 单元时的副作用?
Seq.map and Seq.mapi optimize away side effects when anonymous function returns unit?
在调试记忆函数时,我发现自己试图找出 Seq.mapi
是否真的迭代了一个序列,所以我用 printfn
调用替换了一个匿名函数,如下所示:
let x = "test" |> Seq.map (fun c -> c |> printfn "%c")
令我惊讶的是,打印到控制台的副作用从未发生,在 FSI 中它只是返回 val d : seq<unit>
。虽然这个结果是正确的,但我曾预料到当 map
函数遍历序列时会出现副作用。也就是说,当我用 Seq.map id
替换它时,它按预期工作并且 returns 本身。
当我用 Seq.iter
或 Seq.iteri
替换 Seq.map
或 Seq.mapi
时,它实际上确实打印了副作用。
现在我 认为 这是由于序列被延迟计算,并且 F# 在内部创建了一个闭包序列,或者在它被调用之前实际上什么都不做,因为如果我 Seq.last d
,它 会 打印序列中的所有项目。
F# 中的 seq
是 IEnumerable
的别名,因此 Seq
模块函数大多等同于 Linq。是的,他们被懒惰地评估。
在调试记忆函数时,我发现自己试图找出 Seq.mapi
是否真的迭代了一个序列,所以我用 printfn
调用替换了一个匿名函数,如下所示:
let x = "test" |> Seq.map (fun c -> c |> printfn "%c")
令我惊讶的是,打印到控制台的副作用从未发生,在 FSI 中它只是返回 val d : seq<unit>
。虽然这个结果是正确的,但我曾预料到当 map
函数遍历序列时会出现副作用。也就是说,当我用 Seq.map id
替换它时,它按预期工作并且 returns 本身。
当我用 Seq.iter
或 Seq.iteri
替换 Seq.map
或 Seq.mapi
时,它实际上确实打印了副作用。
现在我 认为 这是由于序列被延迟计算,并且 F# 在内部创建了一个闭包序列,或者在它被调用之前实际上什么都不做,因为如果我 Seq.last d
,它 会 打印序列中的所有项目。
seq
是 IEnumerable
的别名,因此 Seq
模块函数大多等同于 Linq。是的,他们被懒惰地评估。