DIP 1017--Add Bottom Type--Final Review

luckoverthere luckoverthere at gmail.cm
Wed Jan 16 23:40:03 UTC 2019


On Wednesday, 16 January 2019 at 23:08:38 UTC, Paul Backus wrote:
> On Wednesday, 16 January 2019 at 11:23:18 UTC, Johan Engelen 
> wrote:
>> This is just another example of using the bottom type to 
>> signify `noreturn`, which is trivially done with an attribute 
>> and doesn't need a new type. I'd like to see _other_ practical 
>> uses of the bottom type.
>>
>> -Johan
>
> Here's an example I ran into while working on my `expectations` 
> library. [1]
>
> Internally, an Expected!(T, E) is represented as a 
> discriminated union containing either an "expected" value of 
> type T or an error value of type E. I would like to implement a 
> property method, `value`, that either returns the expected 
> value if there is one, or throws an exception if there isn't 
> (similar to Rust's `unwrap`).
>
> The obvious implementation looks like this:
>
> struct Expected(T, E) {
>     private SumType!(T, E) data;
>
>     @property T value() {
>         return data.match!(
>             (T val) => val,
>             (E err) { throw new Exception(err.to!string); }
>         );
>     }
> }
>
> However, this will not compile, because the second lambda is 
> inferred to have a return type of void, and void is not 
> implicitly convertible to T. Instead, I have to resort to the 
> following ugly workaround:
>
> @property T value() {
>     try {
>         return data.tryMatch!(
>             (T val) => val
>         );
>     } catch (MatchException _) {
>         data.tryMatch!(
>             (E err) => throw new Exception(err.to!string)
>         );
>     }
> }
>
> If the second lambda were inferred to have a return type of 
> Tbottom, none of this would be necessary. The first version 
> would Just Work™.
>
> [1] http://expectations.dub.pm

Also a simpler work around to your problem:

struct Expected(T, E) {
     private SumType!(T, E) data;
     @property T value() {
         return data.match!(
             (T val) => val,
             (E err) { throw new Exception(err.to!string); return 
T.init; }
         );
     }
}

Or depending on what you are doing even just using an if 
statement if you only have 2 types like that.


More information about the Digitalmars-d mailing list