Re: [External] : Re: Positioning of guards (was: Reviewing feedback on patterns in switch)

2022-01-26 Thread Brian Goetz
> 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.

I like the && syntax too (though we can invent some nasty puzzlers with 
booleans, such as `case false && false`, which are not so likable.)  But the 
two are not uncoupled; its harder to imagine && as part of the case, and not as 
part of the pattern.  We can of course do many things here, but I worry that 
the choice of operator affects peoples intuition about the semantics.  
(Historically keyword operators like instanceof have the weakest binding 
precedence.)  




Re: Positioning of guards (was: Reviewing feedback on patterns in switch)

2022-01-26 Thread Remi Forax
- Original Message -
> From: "Tagir Valeev" 
> To: "Brian Goetz" 
> Cc: "amber-spec-experts" 
> 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  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`.)


Re: Positioning of guards (was: Reviewing feedback on patterns in switch)

2022-01-25 Thread Tagir Valeev
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);
}
}

On Wed, Jan 26, 2022 at 2:49 AM Brian Goetz  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 intsanceof, 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`.)


Re: Positioning of guards (was: Reviewing feedback on patterns in switch)

2022-01-25 Thread Remi Forax
- Original Message -
> From: "Brian Goetz" 
> To: "amber-spec-experts" 
> Sent: Tuesday, January 25, 2022 8:49:02 PM
> Subject: Positioning of guards (was: Reviewing feedback on patterns in switch)

>> 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 intsanceof, 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`.)

I think it's a good simplification.

Rémi