Draft JEPs: Pattern Matching for switch and Record Patterns
Brian Goetz
brian.goetz at oracle.com
Mon Oct 3 22:16:21 UTC 2022
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" <gavin.bierman at oracle.com>
> *To: *"Tagir Valeev" <amaembo at gmail.com>
> *Cc: *"amber-dev" <amber-dev at openjdk.org>, "amber-spec-experts"
> <amber-spec-experts at openjdk.org>
> *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 at 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 <amaembo at gmail.com> 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
> <gavin.bierman at oracle.com> 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
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-observers/attachments/20221003/e393fa79/attachment-0001.htm>
More information about the amber-spec-observers
mailing list