简体   繁体   中英

F# - Why Seq.map does not propagate exceptions?

Imagine the following code:

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

Now let us test it:

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

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

This works as I would expect. But if we change List to Seq in the function, we get different behavior:

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

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

Here with keys2 I can see the exception message within values object in the debugger but no exception is thrown...

Why is it like this? I need some similar logic in my app and would prefer to work with sequences.

This is a classic example of a problem with side effects and lazy evaluation. Seq functions such as Seq.map are lazily evaluated, that means that the result of Seq.map will not be computed until the returned sequence is enumerated. In your example, this never occurs because you never do anything with values .

If you force the evaluation of the sequence by generating a concrete collection, like a list , you will get your exception and the function will return false :

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

As you've noticed, using List.map instead of Seq.map also resolves your issue because it will be eagerly evaluated when called, returning a new concrete list .

The key takeaway is, you have to be really careful about combining side effects with lazy evaluation. You can't rely on effects happening in the order that you initially expect.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM