So, there are two stable points here: make the where clause part of the pattern, or match it with the case label entirely. The middle option is not stable; a case like
case P, Q when e: Is no longer clear, and worse, if the when clause binds to Q, then we would have to repeat the guard if we wanted `(P|Q) when e`. We explored guards on patterns (P && e) and concluded that it was better treated as part of the switch rather than the pattern. > On Aug 14, 2023, at 8:28 AM, Tagir Valeev <amae...@gmail.com> wrote: > > I don't think that my example is contrived. Let's think of it from > another angle. Are multiple patterns in the same switch label useful > or contrived? If not useful, then let's disable them completely. If > useful, then the next question: are guards with multiple patterns > useful or contrived? Can you imagine a case when the single guard for > the whole label will be useful (provided that we cannot declare any > variables)? I'm not quite sure that a non-contrived example is > possible. So probably we should disable guards with multiple patterns > completely? > > My point is that having a separate guard per pattern is much more > useful and less confusing than having a single guard for all patterns. > You may convince me that I'm wrong by providing not-so-contrived > examples. > > By the way, the following colon-style switch looks supported (though > buggy again, reported JDK-8314226): > > void test(Object obj) { > switch (obj) { > case Integer _ when ((Integer) obj) > 0: > case String _ when !((String) obj).isEmpty(): > System.out.println(obj + ": Positive number or non-empty string"); > break; > default: > System.out.println("other"); > } > } > > And it looks like there's no way to express the same with an > arrow-style switch, or even replace adjacent cases with comma (which > is possible for other cases). > > With best regards, > Tagir Valeev. > > On Mon, Aug 14, 2023 at 5:04 PM Brian Goetz <brian.go...@oracle.com> wrote: >> >> While we could certainly do this, I think the cost-benefit runs in the wrong >> direction here. This sort of thing is better expressed as an if, and that’s >> fine. (I think you’ll agree that this example is a little bit contrived.). >> >>> On Aug 14, 2023, at 5:15 AM, Tagir Valeev <amae...@gmail.com> wrote: >>> >>> Hello! >>> >>> Currently, when the switch label contains several patterns, only one >>> guard could be declared, which is applied to all the patterns at once. >>> In other words, the following code is not possible: >>> >>> void test(Object obj) { >>> switch (obj) { >>> case Integer _ when ((Integer) obj) > 0, >>> String _ when !((String) obj).isEmpty() >>> -> System.out.println("Positive number or non-empty string"); >>> default -> System.out.println("other"); >>> } >>> } >>> >>> Does it make sense to lift this restriction? Probably it could be >>> useful to declare separate guards? Ideally it should be possible to be >>> able to declare a pattern variable, which is visible inside the >>> pattern-specific guard only (but not inside the rule body). >>> >>> Another confusing thing here: >>> >>> void test(Object obj) { >>> switch (obj) { >>> case Integer _, >>> String _ when !((String) obj).isEmpty() >>> -> System.out.println("Number or non-empty string"); >>> default -> System.out.println("other"); >>> } >>> } >>> >>> Now, the guard is applied even if obj is Integer (resulting in >>> ClassCastException). This is not quite evident from the code. We may >>> say that 'when' precedence is lower than ',' precedence, but people >>> may expect the opposite. Should not we reconsider this and make guard >>> a part of the lebel element, rather than the part of the whole label? >>> >>> With best regards, >>> Tagir Valeev. >>