I’m pleased to announce the inital 0.1 release of my new package ErrorTypes.jl.
If you’re familiar with Rust, ErrorTypes introduces limited versions of Rust’s Option<T>
and Result<T, E>
and the recoverable error handling that they provide.
If you’re not familiar with Rust, consider the Julia function maximum
. When applied to an object, it can essentially do one of three things:
-
The object is not iterable or do not have elements that can be compared.
maximum
will fail immediately, and this will be caught in testing. -
It will behave correctly. No problem.
-
The object will be empty, and
maximum
will throw an error.
The last possibility is dangerous, because it’s an edge case that is only caught in testing if the tests are thorough enough to remember the case. Therefore, maximum
provides a trap for downstream users, an easy opportunity to get into trouble.
Suppose instead that maximum(::Vector{Int})
instead of returning an Int
or throwing an error, returned an object of a new type Option{Int}
, which contained either nothing, signifying that the function errored, or the result. Then, it would not be possible to forget the edge case, because the fact that the function is fallible is encoded in its return type. If you forget it can fail and assumes it returns an Int
, you will get a MethodError
.
ErrorTypes should have zero runtime cost in type-stable code (compared to a ===
check against nothing
), so in a sense, you get the improved code robustness and safety for free. The cost you pay is that using ErrorTypes adds a little friction in development because you’ll need to construct and unwrap these “container” types such as Option
. ErrorTypes does provides various convenience methods and macros to make this easier.
The same concept has been tried out in ResultTypes.jl and Expect.jl already. The difference to ErrorTypes are:
-
ErrorTypes provide more convenience methods than Expect.jl, similar to ResultTypes.jl
-
ErrorTypes provide
Option
- a simplified version ofResult
, for when there is no need to encode anything in the error value, in order to cut down on boilerplate. -
Unlike the other packages, ErrorTypes allows you to construct a
Result
with arbitrary types, e.g. aResult{Int, Int}
, where the error can be encoded in anInt
, without the danger of mistaking the error and the result values. The two other packages both require the error value to be anException
. -
ErrorTypes tries to be more strict about return types to cut down on sources of error. It does not allow conversion of error types with concrete values, e.g. an
Option{Int}
cannot be converted to anOption{UInt}
, even if these two integers can be converted to each other. Similarly, a value ofT
cannot be converted to aResult
, instead you must construct aOk(T)
or aErr(T)
.
ErrorTypes builds on @mason’s SumTypes.jl, so thank you @mason, for making the package much nicer.
Please give my package a try. As always, feedback is much appreciated.