[patterns] Several patterns and guards
Tagir Valeev
amaembo at gmail.com
Mon Aug 14 15:28:19 UTC 2023
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.goetz at 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 <amaembo at 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.
>
More information about the amber-spec-experts
mailing list