[pattern-switch] Guards

Brian Goetz brian.goetz at oracle.com
Fri Aug 14 17:20:30 UTC 2020


>
>  - Guards.  (John, Tagir) There is acknowledgement that some sort of 
> "whoops, not this case" support is needed in order to maintain switch 
> as a useful construct in the face of richer case labels, but some 
> disagreement about whether an imperative statement (e.g., continue) or 
> a declarative guard (e.g., `when <predicate>`) is the right choice.

This is probably the biggest blocking decision in front of us.

John correctly points out that the need for some sort of guard is a 
direct consequence of making switch stronger; with the current meaning 
of switch, which is "which one of these is it", there's no need for 
backtracking, but as we can express richer case labels, the risk of the 
case label _not being rich enough_ starts to loom.

We explored rolling boolean guards into patterns themselves (`P && g`), 
which was theoretically attractive but turned out to not be all that 
great.  There are some potential ambiguities (even if we do something 
else about constant patterns, there are still some patterns that look 
like expressions and vice versa, making the grammar ugly here) and it 
just doesn't have that much incremental expressive power, since the most 
credible other use of patterns already (instanceof) has no problem 
conjoining additional conditions, because it's a boolean expression.  So 
this is largely about filling in the gaps of switch so that we don't 
have fall-off-the-cliff behaviors.

There are two credible approaches here:

  - An imperative statement (like `continue` or `next-case`), which 
means "whoops, fell in the wrong bucket, please backtrack to the dispatch";

  - A declarative clause on the case label (like `when <predicate>`) 
that qualifies whether the case is selected.

Most of the discussion so far has been on the axis of "continue is 
lower-level, and therefore better suited to be a language primitive" vs 
"the code that uses guards is easier to read and reason about."  
Assuming we have to do one (and I think we do), we have three choices 
(one, the other, or both.)  I think we should step away from the 
either/or mentality and try to shine a light on what goes well, or 
badly, when we _don't_ have one or the other.

For example, with guards, we can express fine degrees of refinement in 
the case labels:

     case P & g1: ...
     case P & g2: ...
     case P & g3: ...

but without them, we can only have one `case P`:

     case P:
         if (g1) { ... }
         else if (g2) { ... }
         else if (g3) { ... }

My main fear of the without-guards branches is that it will be 
prohibitively hard to understand what a switch is doing, because the 
case arms will be full of imperative control-flow logic.

On the other hand, a valid concern when you have guards is that there 
will be so much logic in the guard that you won't be able to tell where 
the case label ends and where the arm begins.


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


More information about the amber-spec-experts mailing list