[pattern-switch] Guards

Kevin Bourrillion kevinb at google.com
Wed Aug 26 20:53:36 UTC 2020


I think it will usually be easy for users to keep guards simple, by just
extracting out a method when they're not, and the aesthetics will even
motivate them to do that.

With `continue`, there might be any amount of complexity, even state
changes, in the statement group before the `continue` is hit, and it's not
necessarily extractable.

Really, it just seems like we now have two different kinds of fall-through
layered on top of each other. The silent continue is for going to the next
group, while the explicit continue goes back to checking for a match. Why
that way and not the other way around? Just legacy reasons.

I like the guards.



On Fri, Aug 14, 2020 at 10:21 AM Brian Goetz <brian.goetz at oracle.com> wrote:

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

-- 
Kevin Bourrillion | Java Librarian | Google, Inc. | kevinb at google.com


More information about the amber-spec-observers mailing list