0 people like it.
Like the snippet!
Capture the rest of sequence on error
Computation expression that automatically captures the rest of the sequence that you are iterating over using a "for" loop so that the exception handler can do something clever with it.
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:
|
// Used to wrap errors that happen inside for loop body
exception ForLoopException of exn * seq<obj>
// Basic computation builder - the only clever logic is in "for"
type AutoSeqBuilder() =
member x.For(s:seq<'a>, f) =
use en = s.GetEnumerator()
let rec loop() =
if en.MoveNext() then
// If an exception happens during the evaluation of the body,
// capture it alognside with the unused part of the input sequence
try f en.Current
with e ->
let rest = seq {
yield box en.Current
while en.MoveNext() do yield box en.Current }
raise(ForLoopException(e, rest))
loop ()
loop()
member x.Zero() = ()
member x.Combine(a, b) = a; b()
member x.Delay(f) = f
member x.Run(f) = f()
member x.Return(v) = v
member x.TryWith(f, g) =
try f() with e -> g e
let serr = AutoSeqBuilder()
// Example - the exception handler can access the unused part of the sequence!
serr {
try
for i in 0 .. 10 do
if i > 5 then failwith "Too much"
printfn "Processing %d" i
with ForLoopException(e, rest) ->
for v in rest do
printfn "Failed or skipped %O" v }
|
exception ForLoopException of exn * seq<obj>
type exn = System.Exception
Multiple items
val seq : sequence:seq<'T> -> seq<'T>
--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>
type obj = System.Object
Multiple items
type AutoSeqBuilder =
new : unit -> AutoSeqBuilder
member Combine : a:unit * b:(unit -> 'e) -> 'e
member Delay : f:'d -> 'd
member For : s:seq<'a> * f:('a -> unit) -> unit
member Return : v:'b -> 'b
member Run : f:(unit -> 'c) -> 'c
member TryWith : f:(unit -> 'a) * g:(exn -> 'a) -> 'a
member Zero : unit -> unit
--------------------
new : unit -> AutoSeqBuilder
val x : AutoSeqBuilder
val s : seq<'a>
val f : ('a -> unit)
val en : System.Collections.Generic.IEnumerator<'a>
System.Collections.Generic.IEnumerable.GetEnumerator() : System.Collections.Generic.IEnumerator<'a>
val loop : (unit -> unit)
System.Collections.IEnumerator.MoveNext() : bool
property System.Collections.Generic.IEnumerator.Current: 'a with get
val e : exn
val rest : seq<obj>
val box : value:'T -> obj
val raise : exn:System.Exception -> 'T
val a : unit
val b : (unit -> 'e)
val f : 'd
val f : (unit -> 'c)
val v : 'b
val f : (unit -> 'a)
val g : (exn -> 'a)
val serr : AutoSeqBuilder
val i : int
val failwith : message:string -> 'T
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
val v : obj
More information