[patterns] Several patterns and guards

Remi Forax forax at univ-mlv.fr
Mon Aug 14 15:43:49 UTC 2023


----- Original Message -----
> From: "Tagir Valeev" <amaembo at gmail.com>
> To: "Brian Goetz" <brian.goetz at oracle.com>
> Cc: "amber-spec-experts" <amber-spec-experts at openjdk.org>
> Sent: Monday, August 14, 2023 5:28:19 PM
> Subject: Re: [patterns] Several patterns and guards

> 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).

We know that at some point, we will need to lift any methods to a deconstruction pattern, this will solve this kind of example.

static pattern (Integer) isStrictlyPositive(Integer value) {
  if (value > 0) {
    return match value;
  }
  return nomatch;
}

static pattern () isEmpty(String s) {
  if (s.isEmpty()) {
    return match;
  }
  return nomatch;
}

void test(Object obj) {
 switch (obj) {
   case Utils::isStrictlyPositive _, Utils::isEmpty ->
     System.out.println(obj + ": Positive number or non-empty string");
   default ->
     System.out.println("other");
 }
}

> 
> With best regards,
> Tagir Valeev.

regards,
Rémi

> 
> 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