On Sunday, 29 August 2021 at 19:19:54 UTC, SealabJaster wrote:
>On Sunday, 29 August 2021 at 15:05:57 UTC, Paul Backus wrote:
>...
It is also of course totally possible I'm not using sumtypes right, but I'm frequently in situations such as this:
private string expectSingleIdentifier(Token tok, Expression[] exp)
{
string ret;
exp[0].match!(
(IdentifierExpression exp) { ret = exp.ident; },
(_) { throw new Exception(...); }
);
return ret;
}
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:
return exp[0].tryMatch!(
(IdentifierExpression exp) => exp.ident
);
> While in this case I still have to go through match
in order to access the value, sometimes I simply want to do a type check, and going through match
seems a bit overkill.
I guess it's just a niche case (wanting to 'abort' on a bad value rather than keep going) I keep running into, likely a sign I need to change my mindset rather than anything else.
Or I'm just using it as a wrong abstraction >;3
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:
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:
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."
>In this specific case as well I don't believe I can use return match!(...)
because I can't return anything in the "bad" case, since I'd then get an unreachable code error. Very minor yet annoying thing, but that's more a language issue rather than something inherent to SumType.
There is actually a workaround for this:
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.