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