I was skeptical at first too, but the weight of the points Gavin raises
makes me feel that this aspect was (a) a little rushed and (b) not
critical, so backing it out now gives us a chance to think it through
further, and bring it back later in this or another form.
On 10/3/2022 12:25 PM, Remi Forax wrote:
------------------------------------------------------------------------
*From: *"Gavin Bierman" <[email protected]>
*To: *"Tagir Valeev" <[email protected]>
*Cc: *"amber-dev" <[email protected]>, "amber-spec-experts"
<[email protected]>
*Sent: *Monday, October 3, 2022 5:29:40 PM
*Subject: *Re: Draft JEPs: Pattern Matching for switch and Record
Patterns
Hi Tagir,
The main objection to remove the name of the record pattern is that it
does not follow the principle of the data oriented programming.
The idea is that the data is more important than the code, or said
differently, if the data change by example a component is added to a
record, the compiler should flag all the code that uses that record
and ask the user to modify the code.
So a case with a record pattern is better than just a type pattern,
because unlike a type pattern, a record pattern validates the shape of
a record
case Point p // does not validate the shape of Point
case Point(int x, int y) p // validates that a Point has two
components x and y.
When using virtual polymorphism, an operation is defined as an
abstract method, so if the record shape changes, people will scan the
rest of the record and change the implementation of the methods
according to the new components. If the operation uses pattern
matching, the record and the operation are not declared at the same
place, so the compiler has to help users to find all the locations in
the code that should be updated.
So it was a number of issues actually. First, there is a nasty
ambiguity problem. Consider:
record R(){}
switch(e) {
case R() when when (true) -> ...
...
}
The label could be parsed as either:
case (R() when) when (true) ->
or
case (R()) when (when(true)) ->
(where `when` is a static boolean method).
It's a usual issue with local keywords, we had the same kind of issue
with the local keywords inside modules (transitive as a keyword or has
a package name).
A solution on top of my head is to make "when" a keyword for the whole
case (everything in between "case" and "->"), so having to consecutive
"when" is not syntactically valid.
It's not the only option, and i don't think it's a showstopper.
There is another issue which is this variable declaration is the
only one in the language that can’t be annotated or marked as
`final` which feels like a design smell. None of the obvious
solutions to this looked good.
For me, a group pattern is not really different than a type pattern
for this concern,
the current syntax is with a type pattern is
case final Point p ->
so the syntax for a record pattern is
case final Point(int x,int y) p ->
It awkward and super verbose but it's a straight consequence of not
having the binding always final.
In most other languages with pattern matching they keep these two
things - a destructing pattern and a naming pattern - separate. In
both Haskell and Scala, they write `x@p` to “name” a pattern p as
x. So that seems like a possibility. But for now, we noted that in
most cases you can rewrite pretty simply, e.g.
case Point(var x, var y) when p.isVisible() ->
can be rewritten:
case Point p
when p.isVisible() && p instanceof Point(var x, var y): …
or if it was in an instanceof:
if (x instanceof Point p && p.isVisible() && p instanceof
Point(var x, var y)) { … }
Neither of these versions read too badly.
I disagree, a case ... does not exist in the vacuum but works and is
read with the other cases.
Here, following "case Point p when ... ", you will have a proper
record pattern of Point to be exhaustive and the lack of common prefix
between the two patterns makes the code hard to read.
Point p = ...
switch(p) {
case Point p
when p.isVisible() && p instanceof Point (var x, var y) -> ...
case Point(int x, int y) -> ...
}
compared to
Point p = ...
switch(p) {
case Point(int x, int y) p when p.isVisible() -> ...
case Point(int x, int y) p -> ...
}
Here, it's clear that the first line is a peculiar case of the second
line.
Thoughts?
Gavin
Rémi
On 3 Oct 2022, at 14:40, Tagir Valeev <[email protected]> wrote:
Hello!
Remove support for named record patterns.
This surprises me. Probably there was a discussion about the
rationale
behind this change? Could you please point me? Thanks.
With best regards,
Tagir Valeev
On Mon, Oct 3, 2022 at 2:48 PM Gavin Bierman
<[email protected]> wrote:
Dear all,
The draft JEPs for the next preview of the Pattern
Matching for switch and Record Patterns features are now
available at:
Pattern matching for switch:
https://bugs.openjdk.org/browse/JDK-8294285
Record Patterns: https://bugs.openjdk.org/browse/JDK-8294078
Comments welcomed!
Gavin