Java 14 records canonical constructor

Brian Goetz brian.goetz at oracle.com
Thu Jun 4 20:37:40 UTC 2020


> Let's say that normalization is allowed in the canonical constructor, 
> how would that interact with e.g. pattern matching which I assume is 
> the main consumer of the "re-construction" property of records.

Then the constructor ((int, int) -> R) and the deconstructor (R -> (int, 
int)) form a _projection-embedding pair_, which have the property that 
given:

     record R r = ...
     R rr = new R(r.c0(), r.c1(), ... r.cn())

then `rr.equals(r)`.  In other words, the composed function $ctor \dot 
dtor$ is an identity on R (but not necessarily the other way around.)

> Would the following match the first or the second case?
>
> switch (new Rational(1, 2)) {
>     case Rational(2, 4):
>         break;
>     case Rational(1, 2):
>         break;
> }

To ask `x instanceof Rational(2, 4)` (assuming numeric literals are the 
denotation of constant patterns), this expression is equivalent to 
matching the pattern:

     Rational(var _a, var _b)  && _a instanceof 2 && _b instanceof 4

I think there's your answer.  The sub-patterns are not "passed" like 
parameters to the deconstruction pattern; they stay at the use site, and 
are applied monadically if the outer pattern matches.  There is no 
Rational that will match the pattern `Rational(2, 4)`.

> I guess what I am asking is, will the pattern cause a Rational object 
> to be instantiated such that the normalization can happen for that 
> pattern object as well? If not, then it seems to me that a canonical 
> constructor that alters/mutates the arguments is broken and can't be 
> used for pattern matching.

I think maybe you just have a mental model of how records and/or pattern 
matching works, and it isn't quite how it does work. (That's fine, and 
we're happy to educate, but loaded words like "broken" are probably best 
avoided.)

Pattern matching is _destructuring_; taking a whole and destructuring it 
into parts.  The output of a pattern match on a rational is going to be 
some flavor of "numerator and denominator".

I think what you're probably thinking is that asking `x instanceof 
Rational(2, 4)` means "could x have come from the constructor invocation 
`new Rational(2, 4)`.  But that's not what it means. (Though you can ask 
this question easily by: r.equals(new Rational(2,4))`.







More information about the amber-dev mailing list