Thread overview |
---|
July 15, 2016 Result Types and void usage | ||||
---|---|---|---|---|
| ||||
Hi all, I've been using D for a week now to compare it to Rust as a replacement to C++. One thing I miss from Rust is https://doc.rust-lang.org/std/result/ and its companion https://doc.rust-lang.org/std/macro.try!.html They make for some nice syntax so I had a go at recreating them in D (below): One thing I cant figure out/don't know if is possible is to have a type that takes "void" (see last unittest) For example in Rust a can declare a Result of Result<(), ErrorType> however I'm struggling to find the same semantics in D. Of course I can just use a bool but I'd prefer not to. Thank you for your time Nik Result type: struct Result(T, E) { this(inout T result) inout { _result = result; _is_result = true; } this(inout E error) inout { _error = error; _is_result = false; } bool is_result() const pure nothrow @safe @property { return _is_result; } T result() const pure nothrow @safe @property { return _result; } bool is_error() const pure nothrow @safe @property { return !_is_result; } E error() const pure nothrow @safe @property { return _error; } private: T _result; bool _is_result; E _error; } unittest { auto result = Result!(int, string)(1); assert(result.is_result); assert(result.result == 1); } unittest { auto result = Result!(int, string)("error"); assert(result.is_error); assert(result.error == "error"); } unittest { auto result_1 = Result!(int, string)(1); auto result_2 = Result!(int, string)(1); assert(result_1 == result_2); } unittest { auto result_1 = Result!(int, string)(1); auto result_2 = Result!(int, string)(2); assert(result_1 != result_2); } unittest { auto result_1 = Result!(int, string)(1); auto result_2 = Result!(int, string)("error"); assert(result_1 != result_2); } unittest { auto result_1 = Result!(int, string)("error"); auto result_2 = Result!(int, string)("error"); assert(result_1 == result_2); } unittest { auto result_1 = Result!(int, string)("an error"); auto result_2 = Result!(int, string)("error"); assert(result_1 != result_2); } unittest { enum ErrorType{A_Error, B_Error} auto result = Result!(int, ErrorType)(ErrorType.A_Error); assert(result.error() == ErrorType.A_Error); auto result_2 = Result!(immutable(bool), ErrorType)(true); assert(result_2.result()); Result!(immutable(bool), ErrorType) a_method() { return Result!(immutable(bool), ErrorType)(true); } assert(a_method().result()); } unittest { auto result_1 = Result!(bool, string)(true); assert(result_1.result); } //unittest //{ // auto result_1 = Result!(void, string)(void); // auto result_2 = Result!(void, string)(void); // assert(result_1.is_result); // assert(result_1 == result_2); //} |
July 15, 2016 Re: Result Types and void usage | ||||
---|---|---|---|---|
| ||||
Posted in reply to nik | On Friday, 15 July 2016 at 08:11:13 UTC, nik wrote: > //unittest > //{ > // auto result_1 = Result!(void, string)(void); > // auto result_2 = Result!(void, string)(void); > // assert(result_1.is_result); > // assert(result_1 == result_2); > //} You wanted to handle the void case? Because there are no void type you have to check the type at compile time. Enter static if... static if(!is(T == void)) { T result() const pure nothrow @safe @property { return _result; } } static if(!is(T == void)) T _result; static if(!is(T == void)) { this(inout T result) inout { _result = result; _is_result = true; } } else { this() { _is_result = true; //Or whatever semantics Rust use for void result } } And about conditional compilation (static if, version etc...): https://dlang.org/spec/version.html |
July 15, 2016 Re: Result Types and void usage | ||||
---|---|---|---|---|
| ||||
Posted in reply to nik | On 07/15/2016 10:11 AM, nik wrote: > One thing I cant figure out/don't know if is possible is to have a type > that takes "void" (see last unittest) [...] > Result type: > > struct Result(T, E) > { > this(inout T result) inout > { > _result = result; > _is_result = true; > } > > this(inout E error) inout > { > _error = error; > _is_result = false; > } > > bool is_result() const pure nothrow @safe @property > { > return _is_result; > } > > T result() const pure nothrow @safe @property > { > return _result; > } > > bool is_error() const pure nothrow @safe @property > { > return !_is_result; > } > > E error() const pure nothrow @safe @property > { > return _error; > } > private: > T _result; > bool _is_result; > E _error; > } void is somewhat special. It can't be used to declare variables or as a parameter type. So you'll have to approach this a bit differently. You also can't have a struct constructor with zero parameters. You can detect void and make it a special case where slightly different code is generated: ---- struct Result(T, E) { static if (!is(T == void)) this(inout T result) inout { ... } ... T result() const pure nothrow @safe @property { static if (!is(T == void)) return _result; } ... static if (!is(T == void)) T _result; bool _is_result = true; /* important when T is void */ } ---- [...] > //unittest > //{ > // auto result_1 = Result!(void, string)(void); > // auto result_2 = Result!(void, string)(void); `void` can't be an argument in D. Just leave the list empty: `Result!(void, string)()`. > // assert(result_1.is_result); > // assert(result_1 == result_2); > //} |
July 15, 2016 Re: Result Types and void usage | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | On Friday, 15 July 2016 at 11:36:27 UTC, ag0aep6g wrote:
> On 07/15/2016 10:11 AM, nik wrote:
>> [...]
> [...]
>> [...]
>
> void is somewhat special. It can't be used to declare variables or as a parameter type. So you'll have to approach this a bit differently. You also can't have a struct constructor with zero parameters.
>
> [...]
Cool, that's neat and has the syntax I'm looking for.
Thanks for your help
Nik
|
Copyright © 1999-2021 by the D Language Foundation