Pattern matching: next steps after JEP 405

Remi Forax forax at univ-mlv.fr
Wed May 18 19:57:46 UTC 2022


> From: "Brian Goetz" <brian.goetz at oracle.com>
> To: "amber-spec-experts" <amber-spec-experts at openjdk.java.net>
> Sent: Wednesday, May 18, 2022 9:18:01 PM
> Subject: Pattern matching: next steps after JEP 405

> JEP 405 has been proposed to target for 19. But, it has some loose ends that I'd
> like to refine before it eventually becomes a final feature. These include:

> - Inference for record patterns. Right now, we make you spell out the type
> parameters for a generic record pattern, such as:

> case Box<String>(String s):

> We also don't allow parameterizations that are not consistent with the match
> target. While this is clear, it is verbose (and gets worse when there is
> nesting), and also, because of the consistency restriction, the
> parameterization is entirely inferrable. So we would like to allow the
> parameters to be inferred. (Further, inference is relevant to GADTs, because we
> may be able to gather constraints on the pattern from the nested patterns, if
> they provide some type parameter specialization.)
Inference is also something we will need for pattern assignment 

Box<>(var s) = box; 

> - Refined type checking for GADTs. Given a hierarchy like:

> sealed interface Node<T> { }
> record IntNode(int i) implements Node<Integer> { }
> record FloatNode(float f) implements Node<Float> { }

> we currently cannot type-check programs like:

> <T> Node<T> twice(Node<T> n) {
> return switch (n) {
> case IntNode(int x) -> new IntNode(x*2);
> case FloatNode(float x) -> new FloatNode(x*2);
> }
> }

> because, while the match constraints the instantiation of T in each arm of the
> switch, the compiler doesn't know this yet.

> - Varargs patterns. Records can be varargs, but we have an asymmetry where we
> can use varargs in constructors but not in deconstruction. This should be
> rectified. The semantics of this is straightforward; given

> record Foo(int x, int y, int... zs) { }

> just as

> new Foo(x, y, z1, z2)

> is shorthand for

> new Foo(x, y, new int[] { z1, z2 })

> we also can express

> case Foo(var x, var y, var z1, var z2)

> as being shorthand for

> case Foo(var x, var y, int[] { var z1, var z2 })

> This means that varargs drags in array patterns.

> - Array patterns. The semantics of array patterns are a pretty simple extension
> to that of record patterns; the rules for exhaustiveness, applicability,
> nesting, etc, are a relatively light transformation of the corresponding rules
> for record patterns. The only new wrinkle is the ability to say "exactly N
> elements" or "N or more elements".
I wonder if we should not at least work a little on patterns on collections, just to be sure that the syntax and semantics of the patterns on collections and patterns on arrays are not too dissimilar. 

> - Primitive patterns. This is driven by another existing asymmetry; we can use
> conversions (boxing, widening) when constructing records, but not when
> deconstructing them. There is a straightforward (and in hindsight, obvious)
> interpretation for primitive patterns that is derived entirely from existing
> cast conversion rules.
When calling a method / constructing an object, you can have several overloads so you need conversions, those conversions are known at compile time. 
(Note that Java has overloads mostly because there is a rift between primitives and objects, if there was a common supertype, i'm not sure overloads will have carried their own weights.) 

When doing pattern matching, there is no overloads otherwise you will have to decide which conversions to do at runtime. 
Given that one mechanism decide which overload to call at compile time and the other decide which patterns to call at runtime, they are not symmetric. 

You can restrict the set of conversions so there is a bijection between the classes checked at the runtime and the type the user will write, but it's a new mechanism, not an existing symmetry. 

In case of a pattern assignment, this is different because there is only one pattern that have to cover all the type, so in that case, conversions are not an issues because there is no runtime checks. 

> Obviously there is more we will want to do, but this set feels like what we have
> to do to "complete" what we started in JEP 405. I'll post detailed summaries,
> in separate threads, of each over the next few days.

Rémi 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20220518/25bfb641/attachment-0001.htm>


More information about the amber-spec-experts mailing list