gpt4 book ai didi

exception - F# - 为什么 Seq.map 不传播异常?

转载 作者:行者123 更新时间:2023-12-02 23:32:25 24 4
gpt4 key购买 nike

想象一下以下代码:

let d = dict [1, "one"; 2, "two" ]

let CollectionHasValidItems keys =
try
let values = keys |> List.map (fun k -> d.Item k)
true
with
| :? KeyNotFoundException -> false

现在让我们测试一下:

let keys1 = [ 1 ; 2 ]
let keys2 = [ 1 ; 2; 3 ]

let result1 = CollectionHasValidItems keys1 // true
let result2 = CollectionHasValidItems keys2 // false

这正如我所期望的那样。但是如果我们在函数中将 List 更改为 Seq,我们会得到不同的行为:

let keys1 = seq { 1 .. 2 } 
let keys2 = seq { 1 .. 3 }

let result1 = CollectionHasValidItems keys1 // true
let result2 = CollectionHasValidItems keys2 // true

这里使用keys2,我可以在调试器的values对象中看到异常消息,但没有抛出异常...

为什么会这样?我的应用程序中需要一些类似的逻辑,并且更喜欢使用序列。

最佳答案

这是一个具有副作用和惰性求值问题的典型示例。 Seq 函数(例如 Seq.map)是延迟计算的,这意味着 Seq.map 的结果将不会被计算,直到返回的序列被计算。列举了。在您的示例中,这种情况永远不会发生,因为您从未对 values 执行任何操作。

如果您通过生成具体集合(例如列表)来强制对序列求值,您将收到异常,并且该函数将返回false:

let CollectionHasValidItems keys =
try
let values = keys |> Seq.map (fun k -> d.Item k) |> Seq.toList
true
with
| :? System.Collections.Generic.KeyNotFoundException -> false

正如您所注意到的,使用 List.map 而不是 Seq.map 也可以解决您的问题,因为它在调用时会立即进行评估,返回一个新的具体 列表

关键的一点是,您必须非常小心地将副作用与惰性评估结合起来。您不能依赖于按照您最初预期的顺序发生的效果。

关于exception - F# - 为什么 Seq.map 不传播异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45633538/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com