Java 14 records canonical constructor

Remi Forax forax at univ-mlv.fr
Thu Jun 4 20:35:03 UTC 2020


----- Mail original -----
> De: "Remi Forax" <forax at univ-mlv.fr>
> À: "Christian Beikov" <christian.beikov at gmail.com>
> Cc: "Brian Goetz" <brian.goetz at oracle.com>, "amber-dev" <amber-dev at openjdk.java.net>
> Envoyé: Jeudi 4 Juin 2020 22:30:14
> Objet: Re: Java 14 records canonical constructor

> ----- Mail original -----
>> De: "Christian Beikov" <christian.beikov at gmail.com>
>> À: "Brian Goetz" <brian.goetz at oracle.com>, "amber-dev"
>> <amber-dev at openjdk.java.net>
>> Envoyé: Jeudi 4 Juin 2020 22:18:41
>> Objet: Re: Java 14 records canonical constructor
> 
>> Am 04.06.2020 um 21:39 schrieb Brian Goetz:
>>> OK, this seems a totally different question to the one you initially
>>> asked :)
>>>
>>> You're basically saying: why is a record constructor allowed to do
>>> _anything_ other than check invariants?
>>>
>>> I understand where this desire comes from.  But, let's pull on that
>>> string.
>>>
>>> Suppose you want to write a record like:
>>>
>>>     record Rational(int num, int denom) { }
>>>
>>> It seems pretty reasonable to want to normalize the numerator and
>>> denominator to lowest terms; among other things, this makes it easy to
>>> obtain the likely-desired invariant of `new Rational(1, 2)` equals
>>> `new Rational(2, 4)`.  Sure, you could export that responsibility on
>>> the client, or provide a separate factory `Rational::inLowestTerms`,
>>> but surely you see how that is more error-prone.
>> 
>> 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.
>> 
>> 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;
>> }
>> 
> 
> We are starting to be far from the initial thread but this should not compile
> because new Rational(2, 4).equals(new Rational(1, 2)) returns true,
> so your code is equivalent to
>  switch(s) {
>    case "foo" -> ...
>    case "foo" -> ...
>  }
> which currently doesn't compile.

and i stupidly say should not "compile" but it can not be detected at compile time in Java, so it's more a runtime error, interesting,
because we may instead say that the first that match is the one chosen.

Rémi


More information about the amber-dev mailing list