2 people like it.
Like the snippet!
A failed attempt at evaluating sequence items in terms of a try-with block
A broken code example demonstrating how it's you can't catch a single throwing enumeration and continue with F#'s IEnumerable.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
|
// Note that this is incorrect.
open System
open System.Linq
module Seq =
let catchExceptions handler (sequence: _ seq) =
let e = sequence.GetEnumerator()
let evaluateNext () =
try Some (e.Current)
with ex -> handler ex
seq { while e.MoveNext() do
match evaluateNext() with
| Some (item) -> yield item
| None -> () }
// Won't work because e.MoveNext() is actually where the exception would be thrown.
// So I tried:
let catchExceptions handler (sequence: _ seq) =
let e = sequence.GetEnumerator()
let safeMoveNext() =
try
e.MoveNext()
with ex ->
handler ex
true
seq {
while safeMoveNext() do
yield e.Current
}
// This is closer, but also doesn't work.
// It turns out that if F#'s seq e.MoveNext() implementation throws an exception
// it does not advance to the next element. This makes it effectively call
// the handler over and over ad infinitum.
// I haven't been able to find anything about what IEnumerator should do in
// this case, so it's not really a bug. A bit disappointing that you have to make
// sure all exceptions are handled up front when you parallelize though.
// Ah well, better luck next time :)
|
namespace System
namespace System.Linq
module Seq
from Microsoft.FSharp.Collections
val catchExceptions : handler:(exn -> 'a option) -> sequence:seq<'a> -> seq<'a>
Full name: Script.Seq.catchExceptions
val handler : (exn -> 'a option)
val sequence : seq<'a>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Core.Operators.seq
--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>
Full name: Microsoft.FSharp.Collections.seq<_>
val e : Collections.Generic.IEnumerator<'a>
Collections.Generic.IEnumerable.GetEnumerator() : Collections.Generic.IEnumerator<'a>
val evaluateNext : (unit -> 'a option)
union case Option.Some: Value: 'T -> Option<'T>
property Collections.Generic.IEnumerator.Current: 'a
val ex : exn
Collections.IEnumerator.MoveNext() : bool
val item : 'a
union case Option.None: Option<'T>
val catchExceptions : handler:(exn -> unit) -> sequence:seq<'a> -> seq<'a>
Full name: Script.catchExceptions
val handler : (exn -> unit)
val safeMoveNext : (unit -> bool)
More information