"With" for records

Remi Forax forax at univ-mlv.fr
Fri Jun 10 14:28:44 UTC 2022


> From: "Brian Goetz" <brian.goetz at oracle.com>
> To: "amber-spec-experts" <amber-spec-experts at openjdk.java.net>
> Sent: Friday, June 10, 2022 2:44:51 PM
> Subject: "With" for records

> In

> [
> https://github.com/openjdk/amber-docs/blob/master/eg-drafts/reconstruction-records-and-classes.md
> |
> https://github.com/openjdk/amber-docs/blob/master/eg-drafts/reconstruction-records-and-classes.md
> ]

> we explore a generalized mechanism for `with` expressions, such as:

> Point shadowPos = shape.position() with { x = 0 }

> The document evaluates a general mechanism involving matched pairs of
> constructors (or factories) and deconstruction patterns, which is still several
> steps out, but we can take this step now with records, because records have all
> the characteristics (significant names, canonical ctor and dtor) that are
> needed. The main reason we might wait is if there are uncertainties in the
> broader target.

> Our C# friends have already gone here, in a way that fits into C#, using
> properties (which makes sense, as their language is built on that):

> object with { property-assignments }

> The C# interpretation is that the RHS of this expression is a sort of "DSL",
> which permits property assignment but nothing else. This is cute, but I think
> we can do better.

> In our version, the RHS is an arbitrary block of Java code; you can use loops,
> assignments, exceptions, etc. The only thing that makes it "special" is that
> that the components of the operand are lifted into mutable locals on the RHS.
> So inside the RHS when the operand is a Point, there are fresh mutable locals
> `x` and `y` which are initialized with the X and Y values of the operand. Their
> values are committed at the end of the block using the canonical constructor.
GREAT ! 

I've several questions, that we will have to answer later. 

The block is also special because there is an implicit return at the end ? so i believe "return" should be disallowed inside the block, right ? 

Does the lifting that appears at the beginning of the block call all accessors ? or the compiler try to be clever and not call an accessor when its value is not needed. 
For example, in 
point with { y = 3; } 
calling point.y() is useless, or is it something the JIT will take care of ? 

Do we allow "with" followed by an empty block ? As a way to clone a record ? 

About the declaration of local variables, in Java, there is no hiding/shadowing between local variables, so a code like this is rejected ? Or do we introduce a special rule for the hiding of implicit variables ? 
int x = Integer.parseInt(); 
... 
foo(point with { y = 3; }); // x is declared twice because there is an implicit int x = point.x(); 

> This should remind people of the *compact constructor* in a record; the body is
> allowed to freely mutate the special variables (who also don't have obvious
> declarations), and their terminal values determine the state of the record.

> Just as we were able to do record patterns without having full-blown
> deconstructors, we can do with expressions on records as well, because (a) we
> still have a canonical ctor, (b) we have accessors, and (c) we know the names
> of the components.

> Obviously when we get value types, we'll want classes to be able to expose (or
> not) such a mechanism (both for internal or external use).
yes, Complex.default with { re = 3; im = 4; } seems a great fit for value classes. 

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


More information about the amber-spec-experts mailing list