This inclination (guards are simple, continue is complicated) is also supported by the following observation: we just went through a big exercise for (optimistic) totality, but any pattern that is guarded (imperatively or declaratively) can't be assumed to cover anything.  It is far easier to spot a pattern with a guard (even if the guard is `&& false`) and know it doesn't contribute to totality, than to scan the imperative body looking for a `continue`.


On 8/26/2020 4:53 PM, Kevin Bourrillion wrote:
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 <[email protected] <mailto:[email protected]>> 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. |[email protected] <mailto:[email protected]>

Reply via email to