> From: "Dan Heidinga" <[email protected]>
> To: "Remi Forax" <[email protected]>, "Brian Goetz" <[email protected]>
> Cc: "Gavin Bierman" <[email protected]>, "amber-spec-experts"
> <[email protected]>
> Sent: Thursday, January 25, 2024 2:56:54 AM
> Subject: Re: Draft JEP: Derived Record Creation (Preview)

> Remi, is the issue that this design doesn't address 100% of the use cases you
> think should be addressed?

I think it's a little worst because people will use that design for something 
not attended and by that will weaken the concept of records. 

> With expressions provide a way to express clone-but-update-these-fields 
> without
> requiring the user to manually code the update methods. It's a great tradeoff
> to get more expressiveness. The fact that it's not named parameters isn't a
> draw back of the design.

I agree. The problem i see is that users will use it to have named parameters 
anyway. 

> Additionally, I think there's some confusion about what a with expression 
> does.
> You say "the main way it is used teach people to avoid precondtions in record
> constructor" but it doesn't avoid preconditions... The canonical constructor 
> is
> still called.

It does practically, but I've poorly explained the steps that lead to that 
conclusion. 

Let say I have a record Person with a name and an age, the constructor should 
check if the name is not null and if the age is positive, but if this record is 
used has a way to have named parameters, it also needs an empty constructor and 
because record constructors must delegate to the canonical constructor, the 
preconditions will be removed. 

> --Dan

Rémi 

> From: amber-spec-experts <[email protected]> on behalf of
> [email protected] <[email protected]>
> Sent: January 24, 2024 4:43 PM
> To: Brian Goetz <[email protected]>
> Cc: Gavin Bierman <[email protected]>; amber-spec-experts
> <[email protected]>
> Subject: Re: Draft JEP: Derived Record Creation (Preview)

>> From: "Brian Goetz" <[email protected]>
>> To: "Remi Forax" <[email protected]>, "Gavin Bierman" 
>> <[email protected]>
>> Cc: "amber-spec-experts" <[email protected]>
>> Sent: Wednesday, January 24, 2024 9:33:34 PM
>> Subject: Re: Draft JEP: Derived Record Creation (Preview)

>>> And as a general remarks, I hope there will be a following JEP about record
>>> instance creation that allows to use the syntax of a transformation block to
>>> initialize a record.
>>> Because as this have been already discussed on several mailing list, if we 
>>> only
>>> give the derived instance creation syntax, people will twist it to be able 
>>> to
>>> initialize a record by component names, by adding an empty constructor that
>>> does nothing on the record. Defeating the idea that constructors should 
>>> ensure
>>> that an invalid instance is not possible to create.

>> Two things about this.

>> 1. In a sense, there _already is_ a way to create a record instance using the
>> syntax of a transformation block: it is called a compact constructor. If you
>> look carefully, the body of a compact constructor, and RHS of a
>> with-expression, are the same thing -- they are blocks for which N mutable
>> locals magically appear, the block gets run, the final values of those locals
>> are observed, and fed to the canonical constructor of a record.

>> But I know this is not what you mean.

>> 2. You are hoping that this can be turned into something like invoking
>> constructor parameters by name rather than positionally. But it seems that 
>> your
>> argument here is not "because that would be a really good thing", but more
>> "people want it so badly that they will distort their code to do it". But
>> that's never a good reason to add a language feature.
> I agree, but it may be a reasonable reason to *not* introduce a feature if the
> main way it is used teach people to avoid precondtions in record constructor.

> I do not hope anything, i'm not ones that write a record with a dozen fields 
> for
> a living. But seeing how far people (and my students) are willing to go to 
> have
> classes initialized by names, i.e. write a full builder class per record, add 
> a
> dependency on an annotation processor like record-builder or lombok, etc, it's
> easy too see how this feature will be abused.

> Data classes usually:
> - can have a lot of components,
> - are updated because business requirement changes modify the data,
> - are application specific, so unlike methods of the JDK/libraries, it's hard 
> to
> remember them.
> so having a way to create them by spelling each component by name is actually 
> a
> good way to make the code readable.

> That's why people goes to a great length to use named parameters.

> And for the anecdote, a recurrent question of my students with a C background 
> is
> to ask how to initialize a class with the field names like C 99 (*).

>> I think many of the "turn records into builders" proposals (of which there 
>> are
>> many) leave out an important consideration: that the real value of by-name
>> initialization is when you have an aggregate with a large number of 
>> components,
>> most of which are optional. Initializing with

>> new R(a: 1, b: 2, c: 3)

>> is not materially better than

>> new R(1, 2, 3)

>> when R only has three components. It is when R has 26 components, 24 of which
>> are optional, that makes things like:

>> new R(a:1, z :26)

>> more tempting. But the suggestion above doesn't move us towards having an 
>> answer
>> for that, and having to write out

>> new R(a: 1, b : <default-for-b>, c: <default-for-c>, ... z: 26)

>> isn't much of an improvement.

>> For records for which most parameters _do_ have reasonable defaults, then a
>> slight modification of the trick you suggest actually works, and also 
>> captures
>> useful semantics in the programming model:

>> record R(int a /* required */,
>> int b /* optional, default = 0 */,
>> ...
>> int z / * required */) {

>> public R(int a, int z) { this(a, 0, 0, ..., z); }
>> }

>> and you can construct an R with

>> new R(1, 26) with { h = 8; };

>> where the alternate constructor takes the required parameters and fills in
>> defaults for the rest, and then you can use withers from there. (People will
>> complain "but then you are creating a record twice, think of the cost", to
>> which the rejoinder is "then use a value record.")

> It is nice but in a way it does not solve the problem fully because people may
> still want to initialize the required parameters of R with named parameters.

> Rémi
> (*) The same way my students with a Python background (all my student 
> nowadays,
> because in France, Python is now mandatory in highschool) ask how to create a
> tuple in Java.

Reply via email to