An exception that represents an error value.
Creates an Expected object from an error value, with type inference.
Unwraps a result, yielding the content of expected value. If there is none, or error value, it throws assert(0) with the provided message.
Unwraps a result, yielding the content of an error value. If there is none, or success value, it throws assert(0) with the provided message.
Creates an Expected object from an expected value, with type inference.
Default hook implementation for Expected
Hook implementation that behaves like a thrown exception. It throws Exception right when the Expected with error is initialized.
Expected!(T, E) is a type that represents either success or failure.
Hook implementation that behaves same as Abort hook, but uses refcounted payload instead, which also enables us to check, if the result was properly checked before it is discarded.
Hook implementation that throws exceptions instead of default assert behavior.
Constructs Expected from the result of the provided function.
Template to determine if hook provides function called on empty error.
Template to determine if hook provides function called on empty value.
Template to determine if hook provides function called when error is set.
Template to determine if hook provides custom handler for case when the Expected result is not checked.
Template to determine if hook provides function called when value is set.
Template to determine if hook enables or disables copy constructor.
Template to determine if provided Hook enables default constructor for Expected
Template to determine if hook defines that the Expected storage should use refcounted state storage.
Template to determine if provided Hook enables void values for Expected
Applies a function to the expected value in an Expected object.
Applies a function to the expected error in an Expected object.
Maps a Expected<T, E> to U by applying a function to a contained value, or a fallback function to a contained error value.
1 auto foo(int i) { 2 if (i == 0) return err!int("oops"); 3 return ok(42 / i); 4 } 5 6 version (D_Exceptions) 7 { 8 auto bar(int i) { 9 if (i == 0) throw new Exception("err"); 10 return i-1; 11 } 12 } 13 14 // basic checks 15 assert(foo(2)); 16 assert(foo(2).hasValue); 17 assert(!foo(2).hasError); 18 assert(foo(2).value == 21); 19 20 assert(!foo(0)); 21 assert(!foo(0).hasValue); 22 assert(foo(0).hasError); 23 assert(foo(0).error == "oops"); 24 25 // void result 26 assert(ok()); // no error -> success 27 assert(!ok().hasError); 28 // assert(err("foo").hasValue); // doesn't have hasValue and value properties 29 30 version (D_Exceptions) 31 { 32 // expected from throwing function 33 assert(consume!bar(1) == 0); 34 assert(consume!bar(0).error.msg == "err"); 35 } 36 37 // orElse 38 assert(foo(2).orElse!(() => 0) == 21); 39 assert(foo(0).orElse(100) == 100); 40 41 // andThen 42 assert(foo(2).andThen(foo(6)) == 7); 43 assert(foo(0).andThen(foo(6)).error == "oops"); 44 45 // map 46 assert(foo(2).map!(a => a*2).map!(a => a - 2) == 40); 47 assert(foo(0).map!(a => a*2).map!(a => a - 2).error == "oops"); 48 49 // mapError 50 assert(foo(0).mapError!(e => "OOPS").error == "OOPS"); 51 assert(foo(2).mapError!(e => "OOPS") == 21); 52 53 // mapOrElse 54 assert(foo(2).mapOrElse!(v => v*2, e => 0) == 42); 55 assert(foo(0).mapOrElse!(v => v*2, e => 0) == 0);
import exp = expected; // define our Expected type using Exception as Error values // and Throw hook, which throws when empty value or error is accessed template Expected(T) { alias Expected = exp.Expected!(T, Exception, Throw); } // create wrappers for simplified usage of our Expected auto ok(T)(T val) { return exp.ok!(Exception, Throw)(val); } auto err(T)(Exception err) { return exp.err!(T, Throw)(err); } // use it as normal assert(ok(42) == 42); assert(err!int(new Exception("foo")).orElse(0) == 0); assertThrown(ok(42).error); assertThrown(err!int(new Exception("bar")).value);
BSL-1.0
This module is implementing the Expected idiom.
See the Andrei Alexandrescu’s talk (Systematic Error Handling in C++ and its slides.
Or more recent "Expect the Expected" by Andrei Alexandrescu for further background.
It is also inspired by C++'s proposed std::expected and Rust's Result.
Similar work is expectations by Paul Backus.
Main features
Description
Actual Expected type is defined as Expected!(T, E, Hook), where:
Default type for error is string, i.e. Expected!int is the same as Expected!(int, string).
Abort is used as a default hook.
Hooks
Expected has customizable behavior with the help of a third type parameter, Hook. Depending on what methods Hook defines, core operations on the Expected may be verified or completely redefined. If Hook defines no method at all and carries no state, there is no change in default behavior.
This module provides a few predefined hooks (below) that add useful behavior to Expected:
That means when function returns expected value, it returns instance of Expected with a success value. But when it tries to return error, Exception is thrown right away, i.e. Expected fails in constructor.
The hook's members are looked up statically in a Design by Introspection manner and are all optional. The table below illustrates the members that a hook type may define and their influence over the behavior of the Checked type using it. In the table, hook is an alias for Hook if the type Hook does not introduce any state, or an object of type Hook otherwise.