Skip to content

Commit ba9ef7d

Browse files
committed
Add Prelude.reraise'
helper funstion to easy reraise exceptions even outside of try-with
1 parent d995800 commit ba9ef7d

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

src/FSharpx.Extras/ComputationExpressions/Monad.fs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,12 @@ module Option =
244244
| Some x -> x
245245
| None -> raise e
246246

247+
/// Gets the value associated with the option or reraises the supplied exception.
248+
let inline getOrReraise e =
249+
function
250+
| Some x -> x
251+
| None -> reraise' e
252+
247253
/// Gets the value associated with the option or the default value for the type.
248254
let getOrDefault =
249255
function
@@ -748,12 +754,19 @@ module Choice =
748754
| Choice2Of2 e -> invalidArg "choice" (sprintf "The choice value was Choice2Of2 '%A'" e)
749755
750756
/// If Choice is 1Of2, return its value.
751-
/// Otherwise throw the exception in 2Of2.
757+
/// Otherwise raise the exception in 2Of2.
752758
let getOrRaise<'a, 'exn when 'exn :> exn> (c:Choice<'a, 'exn>) =
753759
match c with
754760
| Choice1Of2 r -> r
755761
| Choice2Of2 e -> raise e
756762

763+
/// If Choice is 1Of2, return its value.
764+
/// Otherwise reraise the exception in 2Of2.
765+
let getOrReraise<'a, 'exn when 'exn :> exn> (c:Choice<'a, 'exn>) =
766+
match c with
767+
| Choice1Of2 r -> r
768+
| Choice2Of2 e -> reraise' e
769+
757770
/// Wraps a function, encapsulates any exception thrown within to a Choice
758771
let inline protect f x =
759772
try
@@ -1073,7 +1086,7 @@ module Task =
10731086

10741087
let wrapCrash (e:exn) : Task<'a> =
10751088
compensation()
1076-
raise e
1089+
reraise' e
10771090

10781091
this.Bind(this.TryWith(body, wrapCrash), wrapOk)
10791092

@@ -1151,7 +1164,7 @@ module Task =
11511164

11521165
let wrapCrash (e:exn) : TokenToTask<'a> =
11531166
compensation()
1154-
raise e
1167+
reraise' e
11551168

11561169
this.Bind(this.TryWith(body, wrapCrash), wrapOk)
11571170

@@ -1243,4 +1256,4 @@ module Task =
12431256
/// Creates a task that executes all the given tasks.
12441257
/// The paralelism is throttled, so that at most `throttle` tasks run at one time.
12451258
let ParallelWithThrottle throttle (tasks : seq<unit -> Task<'a>>) : (Task<'a[]>) =
1246-
ParallelWithThrottleCustom Choice.getOrRaise throttle tasks
1259+
ParallelWithThrottleCustom Choice.getOrReraise throttle tasks

src/FSharpx.Extras/Prelude.fs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
open System
44
open System.Globalization
55
open System.Diagnostics
6+
open System.Runtime.ExceptionServices
67

78
[<AutoOpen>]
89
module Prelude =
@@ -74,6 +75,14 @@ module Prelude =
7475
/// Custom operator for `tee`: Given a value, apply a function to it, ignore the result, then return the original value.
7576
let inline (|>!) x fn = tee fn x
7677

78+
/// Rethrows an exception. This can be used even outside of try-with block. The exception object (stacktrace, etc) is not changed.
79+
let reraise' (e:exn) : 'T = ExceptionDispatchInfo.Capture(e).Throw() ; undefined
80+
// http://thorarin.net/blog/post/2013/02/21/Preserving-Stack-Trace.aspx
81+
// https://stackoverflow.com/questions/7168801/how-to-use-reraise-in-async-workflows-in-f
82+
83+
/// Rethrows an exception, but bebore that applies a function on it. This can be used even outside of try-with block. The exception object (stacktrace, etc) is not changed.
84+
let reraiseWith (f : exn -> unit) (e:exn) : 'T = f e ; reraise' e
85+
7786
let inline toOption x = match x with
7887
| true, v -> Some v
7988
| _ -> None

0 commit comments

Comments
 (0)