Next up for patterns: type patterns in switch
Alex Buckley
alex.buckley at oracle.com
Thu Aug 13 23:35:10 UTC 2020
On 7/23/2020 11:52 AM, Brian Goetz wrote:
> On 7/23/2020 2:38 PM, Remi Forax wrote:
>> On guards, they do not work well with exhaustiveness. Still not sure
>> they are useful.
>
> It works fine, it's just more work for the user to get right.
>
> We induce a domination ordering on patterns. If `T <: U`, then `T t` <
> `U u` (`T t` is less specific than `U u`.) Similarly, for all guard
> conditions g, `P & g` < `P`. What this says is that if you want
> exhaustiveness, you need an unguarded pattern somewhere, either:
>
> case A:
> case B & g:
> case B: // catches B & !g
> case C:
>
> or
>
> case A:
> case B & g:
> case C:
> case Object: // catches B & !g
>
> I understand your diffidence about guards, but I'm not sure we can do
> nothing. The main reason that some sort of guards feel like a forced
> move (could be an imperative guard, like `continue`, but I don't think
> anyone would be happy with that) is that the fall-off-the-cliff behavior
> is so bad. If you have a 26-arm switch, and you want the equivalent of
> the second of the above cases -- B-but-not-g gets shunted into the
> bottom clause -- you may very well have to refactor away from switch, or
> at least mangle your switch badly, which would be pretty bad.
Is the following what you mean by "mangle your switch badly" ?
switch (o) {
case A: ...
case B: do some B-ish stuff ... also, if (g) {...}
case C: ...
...
case Z: ...
case Object: if (o instanceof B && !g) { do the B-ish non-g thing }
}
Is a guard (a) part of the `case` construct, or (b) part of the pattern
operand for a `case` construct? The original mail introduced "guard
expression" as "a boolean expression that conditions whether the case
matches", which sounds like (a). However, the purpose of a `case`
construct is to enumerate one or more possible values of the selector
expression, and if a `case` construct has a post-condition `& g()` then
it's not just enumerating, and it isn't a `case` construct anymore. I
mean, we don't want to see guards in the `case` constructs of legacy
switches, right? (`switch (i) { case 100 & g():`) So, is the answer (b) ?
Alex
More information about the amber-spec-experts
mailing list