----- Original Message ----- > From: "Tagir Valeev" <amae...@gmail.com> > To: "Brian Goetz" <brian.go...@oracle.com> > Cc: "amber-spec-experts" <amber-spec-experts@openjdk.java.net> > Sent: Wednesday, January 26, 2022 4:50:05 AM > Subject: Re: Positioning of guards (was: Reviewing feedback on patterns in > switch)
> Hello! > > For the record: I like the current version with &&. It's short and > easy to understand (as people already know what && means in Java). I > see no reason in replacing it with `when`, which is more limiting. > >> because of the potential confusion should we ever choose to support switch >> over >> boolean > > It looks like any boolean expression that is a potentially constant > differs syntactically from the guarded pattern, so we can distinguish > between guarded pattern with && and boolean expression on AST level > without resolving the references. End users will unlikely use anything > other than explicit 'true' and 'false' constants, so it will add some > complexity to the compiler but does not add any problems to real users > >> because the && did not stand out enough as turning a total pattern into a >> partial one > > I think it's a matter of taste and habit. I, for one, already get used > to it. It signals about partiality much more, compared to a simple > type pattern. Looking at `CharSequence cs`, you cannot say whether > it's total or not if you don't know the type of the selector > expression. However, looking at `CharSequence cs && cs.length() > 0` > you are completely sure it's not total. So if we need a clear signal > to tell total and partial patterns apart, we have much bigger problems > with type patterns. > >> Guarded patterns are never total > Except when guard is a constant expression that evaluates to `true`: > > void test(Object obj) { > switch (obj) { // compiles > case Object s && true -> System.out.println(s); > } > } I think we should separate the two ideas in Brian's mail, one is should we allow a guard inside a pattern ? and the other is what is the syntax for a guard ? My position is that we should only allow guard in a switch, not as pattern. And i see no problem to use "&&" instead of "when", as Tagir, i'm kind of used to it too. regards, Rémi > > On Wed, Jan 26, 2022 at 2:49 AM Brian Goetz <brian.go...@oracle.com> wrote: >> >> > 2. Positioning of guards >> >> We received several forms of feedback over the form and placement of guarded >> patterns. Recall that we define a guarded pattern to be `P && g`, where P >> is a >> pattern and g is a boolean expression. Guarded patterns are never total. >> Note >> that we had a choice of the guard being part of the pattern, or being part of >> the `case` label; the current status chooses the former. (Part of our >> reasoning was that there might be other partial pattern contexts coming, and >> we >> didn’t want to solve this problem each time. (For instanceof, it makes no >> difference.) ) >> >> I am prepared to reconsider the association of the guard with the pattern, >> and >> instead treat it as part of the case. This is expressively weaker but may >> have >> other advantages. >> >> Additionally, people objected to the use of &&, not necessarily because >> “keywords are better”, but because of the potential confusion should we ever >> choose to support switch over boolean, and because the && did not stand out >> enough as turning a total pattern into a partial one. What the alternative >> looks like is something like: >> >> switch (x) { >> case Foo(var x, var y) >> when x == y -> A; >> case Foo(var x, var y) -> B; >> } >> >> Here, `when` (bike shed to be painted separately) is a qualifier on the case, >> not the pattern. A total pattern with a `when` is considered a partial case. >> This simplifies patterns, and moves the complexity of guards into switch, >> where arguably it belongs. >> >> The loss of expressiveness is in not allowing nested patterns like: >> >> P(Q && guard) >> >> and instead having to move the guard to after the matching construct. Some >> users recoiled at seeing guards inside pattern invocations; it seemed to some >> like mixing two things that should stay separate. (For unrolling a nested >> pattern, `case P(Q)` where Q is not total unrolls to `case Pvar alpha) when > > alpha instanceof Q`.)