Derived record creation and Data Oriented programming
Brian Goetz
brian.goetz at oracle.com
Tue Apr 30 16:22:01 UTC 2024
>
> So let's back up: what problem are we trying to solve here?
>
>
> The problem is that the syntax of "with" does not show that with
> depends on the deconstructor and the constructor of the record, so the
> behavior in case of separate compilation is not clear.
I think the lack of clarity you are concerned about is that the names of
the components are being used as a new kind of API, where we lift API
elements to variables, and you're concerned that those names are "weakly
coupled" between declaration and client? Is this right?
> I see several ways to fix that:
> - restrict the uses of "with" to the package/module containing the
> record (as we have done with sealed types),
With this restriction, I think the feature is not really useful enough
to justify. Plus this will annoy people.
> - allows a syntax variation where the components of the record are listed,
So, this would be like a C++ lambda:
// don't take the syntax seriously, purely meant to evoke C++
lambda syntax
p = p with [x,y]{ x = 3; }
and then the [x,y] would be used for the ctor/dtor lookup?
> - link the canonical deconstructor/constructor of the record at
> runtime (which can be simpler if the local variable declared outside
> of the block are captured (like the variables inside a "when"
> expression)).
Not sure what you mean here, but it probably doesn't scale to classes?
> and maybe there are other solutions ?
>
> Rémi
>
>
> On 4/30/2024 9:22 AM, Remi Forax wrote:
>
> Hello,
> they have been several messages on amber-dev about the compatibility of the derived record creation.
>
> I think part of the issue reported is that with the proposed syntax, the call to the desconstructor and the canonical constructor is implicit.
>
> Let's take an example
>
> record Point(int x, int y) {}
>
> var point = new Point(2, 3);
>
>
> In fact,
> var point2 = point with { x = y; };
>
> is a shortcut for:
>
> var point2 = point with {
> Point(int x, int y) = this; // i.e. int x = this.x(); int y = this.y();
> x = y;
> yield new Point(x, y);
> };
>
> One problem with the current syntax is that because the call to the [de]constructors is implicit. I think we shoud allow users to write the implicit calls if they want.
>
> I wonder if
> - we should not allow yield to be used so the compiler adds yield automatically only if there is no yield ?
> - we should in the future when deconstructors are introduced, allow users to call a deconstructor explicitly and only provide one if not explicitly written ?
>
> Being able to write the calls explicitly is important because it's a way to detect if the record has been modified without the proper constructor/destructor has been written to be backward compatible (Like in a switch, a record pattern detects when a record component is added while a type pattern does not).
>
> Being able to call a the deconstructor explicitly also have the advantage to avoid to declare a variable/calls the accessor if not needed.
> By example
> var point2 = point with {
> Point(_, var y) = this;
> x = y;
> };
>
> regards,
> Rémi
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-experts/attachments/20240430/52156c67/attachment.htm>
More information about the amber-spec-experts
mailing list