I have been coding F# for a while now, and I've managed to stay away from throwing custom exception so chances are I'm doing something wrong now as I'm looking into throwing one, but I thought I would share it, as it also shows how you can accomplish similar constructs as failwithf
to allow formatted messages.
Lets start with the simple part, defining the exception
type ProtocolVersion =
| V1 = 1
exception ProtocolException of ProtocolVersion * string
Raising this exception would be as simple as:
raise (ProtocolException (ProtocolVersion.V1, "Unknown marker found for Encoding."))
And if we want to inject some values in the string:
raise (ProtocolException (ProtocolVersion.V1, sprintf "%i reads '%s'." 42 "fourty two"))
What I want i something like failwith
and failwithf
:
raise (protocol1Exception "Unknown marker found for Encoding.")
and:
raise (protocol1Exceptionf "%i reads '%s'." 42 "fourty two")
One working solution
I'm honestly not sure if this is THE solution, but it's at least a solution, but feel free to educate me of improvements. As F# is Open Source we can have a look at how e.g. failwithf
has been implemented: https://github.com/fsharp/fsharp/blob/cb6cb5c410f537c81cf26825657ef3bb29a7e952/src/fsharp/FSharp.Core/printf.fs#L1645
And looking at this we can put together a working solution like this:
let protocol1Exception message =
ProtocolException (ProtocolVersion.V1, message)
let protocol1Exceptionf format =
Printf.ksprintf protocol1Exception format
Trying it out:
let willThrow() =
raise (protocol1Exception "Unknown marker found for Encoding.")
let willThrow'() =
raise (protocol1Exceptionf "%i reads '%s'." 42 "fourty two")
try
willThrow()
with
| ProtocolException (v,m) -> printfn "Exception message: %s; ProtocolVersion: '%A';" m v
try
willThrow'()
with
| ProtocolException (v,m) -> printfn "Exception message: %s; ProtocolVersion: '%A'" m v
Gives:
1: Exception message: Unknown marker found for Encoding.; ProtocolVersion: 'V1';
2: Exception message: 42 reads 'fourty two'.; ProtocolVersion: 'V1'
That's it for this time. Again, feel free to educate me about improvements. Not only about the implementation in itself but also things like: "you should really not throw, but use e.g Result and ROP instead".
Cheers,
//Daniel