Guards
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Fri Mar 5 22:11:31 UTC 2021
This seems like a nice landing.
The unification of guards and AND patterns was clever, and clearly
compositional, but exposing AND patterns just to get to guards can seem
a daunting step.
I agree that the priority, language design-wise is to get the combo
switch/case and if/instanceof on roughly the same expressive footing.
Without _some_ kind of guard-like capabilities, doing patterns in
switches is gonna be very limited, and some code will necessarily fall
off the expressiveness cliff and be rewritten as an if/else chain.
I think the `when(expr)` syntax is a minor detour; it's easy on the eye
and, as you show, has a gentle progression as to where we are headed.
Personally, given how common the basic guard use case is, I don't mind a
little bit of sugar sprinkled here and there, even though yes, it does
create two ways to do the same thing.
Cheers
Maurizio
On 05/03/2021 19:14, Brian Goetz wrote:
> Let me try and summarize all that has been said on the Guards topic.
>
> #### Background and requirements
>
> For `instanceof`, we don't need any sort of guard right now (with the
> patterns we have); we can already conjoin arbitrary boolean
> expressions with `&&` in all the contexts we can use `instanceof`,
> because it's a boolean expression. (This may change in the future as
> patterns get richer.) So we can already express our canonical guarded
> Point example with
>
> if (p instanceof Point(var x, var y) && x > y) { ... }
>
> with code that no one will find confusing.
>
> For switch, we can't do this, because case labels are not boolean
> expressions, they're some ad-hoc sub-language. When the sub-language
> was so limited that it could only express int and string constants,
> this wasn't a problem; there was little refinement needed on `case
> "Foo"`.
>
> As we make switch more powerful, we face a problem: if the user drifts
> out of the territory of what can be expressed as case labels, they
> fall off the cliff and have to refactor their 50-way switch into an
> if-else chain. This will be a really bad user experience. Some sort
> of escape hatch to boolean logic buys us insurance against this bad
> experience -- as long as you can express your non-pattern criteria
> with a boolean expression (which is pretty rich), you don't have to
> leave switch-land.
>
> So we took as our requirement:
>
> Some sort of guard construct that is usable in switch is a forced
> move.
>
> #### Expressing guards in switch
>
> There are several ways to envision guards:
>
> - As patterns that refine other patterns (e.g., a "true" pattern)
> - As an additional feature of "case" in switch (e.g., a "when" clause)
> - As an imperative control-flow statement usable in "switch" (e.g.,
> "continue")
>
> We've largely rejected the third (even though it is more primitive
> than the others), because we think the resulting code will be much
> harder to read and more error-prone. We've bounced back and forth
> between "let's nail something on the side of switch" and "let's let
> the rising pattern tide lift all conditional constructs."
>
> Other languages have demonstrated that guards in switch-like
> constructs are viable.
>
> The argument in favor of nailing something on the side of switch is
> that it is pragmatic; it is immediately understandable, it raises the
> expressivity of `switch` to where `if` already is, and it solves the
> immediate requirement we have in adding patterns to switch.
>
> The argument against is that it is not a primitive; it is dominated by
> the option of making patterns richer (by adding boolean patterns), it
> is weak and non-compositional, and overly specific to switch. (It is
> possible to make worse-is-better arguments here that we should do this
> anyway, but it's not really possible to seriously claim better,
> despite attempts to the contrary.)
>
> #### Interpreting the feedback
>
> The JEP proposes a powerful and compositional approach:
>
> - true/false patterns that accept arbitrary boolean expressions (and
> which ignore their target);
> - combining patterns with a pattern-AND combinator
>
> On the one hand, this is a principled, orthogonal, compositional,
> expressive, broadly applicable approach, based on sensible primitives,
> which will be usable in other contexts, and which anticipate future
> requirements and directions.
>
> On the other hand, there has been a pretty powerful emotional
> reaction, which could be summarized as "sorry, we're not ready for
> this degree of generality yet with respect to patterns." This
> emotional reaction seems to have two primary components:
>
> - A "who moved my cheese" reaction to the overloading of `true` in
> this way -- that `true` seems to be, in everyone's mind, a constant,
> and seeing it as a pattern is at least temporarily jarring. (This may
> be a temporary reaction, but there's still a cost of burning through it.)
>
> - A reaction to "borrowing & from the future" -- because the other
> use cases for &-composition are not obvious or comfortable yet, the
> use of &-composition seems foreign and forced, and accordingly
> engenders a strong reaction.
>
> The former (which I think is felt more acutely) could be addressed by
> taking a conditional keyword such as `when` here; ad-hoc "focus"
> research suggests the negative reaction here is lower, but still there.
>
> The latter is, I think, the more linguistically significant of the
> two; even though there is a strong motivation for & coming down the
> pike, this is not the gentle introduction to pattern combination that
> we'd like, and developer's mental models of patterns may not be
> ready. Patterns are still new, and we'd like for the initial
> experience to make people want more, rather than scare them with too
> much up front.
>
> #### Options
>
> I suspect that we'd get a lot of mileage out of just renaming true to
> something like "when"; it avoids the "but that's not what true is"
> reaction, and is readable enough:
>
> case Foo(var x) & when(x > 0):
>
> but I think it will still be perceived as "glass half empty", with
> lots of "why do I need the &" reactions. And, in the trivial (but
> likely quite common, at least initially) case of one pattern and one
> guard, the answers are not likely to be very satisfying, no matter how
> solidly grounded in reality, because the generality of the
> compositional approach is not yet obvious enough to those seeing
> patterns for the first time.
>
> I am not compelled by the direction of "just add guards to switch and
> be done with it", because that's a job we're going to have to re-do
> later. But I think there's a small tweak which may help a lot: do
> that job now, with only a small shadow of lasting damage:
>
> - Expose `grobble(expr)` clauses as an option on pattern switch cases;
>
> - When we introduce & combination (which can be deferred if we have a
> switch guard now), plan for a `grobble(e)` pattern. At that point,
>
> case Foo(var x) grobble(x > 0):
>
> is revealed to be sugar for
>
> case Foo(var x) & grobble(x > 0):
>
> As as bonus, we can use grobble by itself in pattern switches to
> incorporate non-target criteria:
>
> case grobble(e):
>
> which is later revealed to be sugar for:
>
> case Foo(var _) & grobble(e):
>
> The downside here is that in the long run, we have something like the
> C-style array declarations; in the trivial case of a single pattern
> with a guard, you can leave in the & or leave it out, not unlike
> declaring `int[] x` vs `int x[]`. Like the "transitional" (but in
> fact permanent) sop of C-style declarations, the "optional &" will
> surely become an impediment ("why can I leave it out here, but not
> there, that's inconsistent").
>
> All that said, this is probably an acceptable worse-is-better
> direction, where in the short term users are not forced to confront a
> model that they don't yet understand (or borrow concepts from the
> future), with a path to sort-of-almost-unification in the future that
> is probably acceptable.
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20210305/69c94869/attachment.htm>
More information about the amber-spec-experts
mailing list