std.sumtype?

JG JG at somewhere.com
Sun Aug 29 23:02:45 UTC 2021


On Sunday, 29 August 2021 at 19:51:30 UTC, Paul Backus wrote:
> On Sunday, 29 August 2021 at 19:19:54 UTC, SealabJaster wrote:
>> [...]
>
> For cases like this you can use `tryMatch`, which does not 
> require exhaustiveness and throws an exception at runtime if it 
> encounters a type with no handler:
>
> ```d
> return exp[0].tryMatch!(
>     (IdentifierExpression exp) => exp.ident
> );
> ```
>
>> [...]
>
> If "abort unless this `SumType` contains a particular type" is 
> a common pattern in your code I would suggest extracting it 
> into a helper function:
>
> ```d
> void require(T, S)(S s)
>     if (isSumType!S)
> {
>     s.match!(
>         (T t) {}
>         (_) { assert(0); }
>     );
> }
> ```
>
> But in general, I think this is the wrong approach. What I 
> would do instead is create a helper function like the following:
>
> ```d
> Optional!T maybeGet(T, S)(S s)
>     if (isSumType!S)
> {
>     return s.match!(
>         (T t) => some(t),
>         _ => no!T;
>     );
> }
> ```
>
> This narrows the set of cases you have to deal with from 
> "anything that could be in the `SumType`" to "either `T` or not 
> `T`", and from there you can handle the "not `T`" case however 
> you want--abort, throw an exception, etc.
>
> The general principle here is ["Parse, don't validate."][1]
>
> [1]: 
> https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/
>
>> [...]
>
> There is actually a workaround for this:
>
> ```d
> return exp[0].match!(
>     (IdentifierExpression exp) => exp.ident,
>     function string (_) { throw new Exception("..."); }
> );
> ```
>
> Note the explicit return type of `string` on the second lambda. 
> The compiler will allow this, even though the lambda never 
> returns a `string`, because it never returns normally at all.

I have used something like the following (although I am finding I 
use this type of thing less the longer I use sumtype):

     import std;

     struct A {}
     struct B {}

     alias Sum = SumType!(A,B);

     T asserter(T)(string errMsg,string file =__FILE__,ulong 
line=__LINE__)
     {
         assert(0,format("%s(%s): %s",file,line,errMsg));
     }

     T as(T,S)(S s, string file=__FILE__,ulong line=__LINE__) 
if(isSumType!S)
     {
         return s.match!((T t)=>t,_=>asserter!T("Sum contains 
unexpected type",file,line));
     }

     void main()
     {
         Sum s = Sum(A.init);
         auto a = s.as!A;
         writeln(a);
         auto b = s.as!B;
     }


More information about the Digitalmars-d mailing list