Next up for patterns: type patterns in switch

Brian Goetz brian.goetz at oracle.com
Fri Aug 14 11:24:10 UTC 2020


> 
> 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 }
> }

Worse!  What I meant is that if you do not have guards, you have to move such stuff OUTSIDE of the switch.  Instead of:

    case B & g: …
    case B: b-logic
    case Object: default-logic

you have to do 

    switch (x) {
        case B: 
            if (!g) { break out of the switch! }
            B logic;
        case Object: 
            default-logic;
     }

    if (it was B but not G) {
       do the default logic again
    }

The problem with a guard-less switch is that you get exactly one chance to fall into one of the buckets, and once you’re in a bucket, your only choice is to fall out of the switch.  

> Is a guard (a) part of the `case` construct, or (b) part of the pattern operand for a `case` construct?

Good question.  We went back and forth a few times on this.  

My initial preference was to make the guard logic part of the pattern; ideally, to make “Pattern && boolean-expr” a pattern.  But this is messy, since it invites ambiguities, and not really needed in the other primary consumer of patterns, since boolean expressions can already be  conjoined with &&, and flow scoping already does everything we want.  The real problem is switch is too inflexible, a problem revealed  when its case labels are made more powerful.  So it seems that the sensible t hing to do is to make guards a feature of switch, and say a case label is one of: 

    case <constant>
    case <pattern>
    case <pattern> when <guard>


> 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) ?

Does the above grammar suggestion answer your question?


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20200814/5dc66971/attachment.htm>


More information about the amber-spec-experts mailing list