> On Apr 24, 2020, at 2:24 PM, Brian Goetz <[email protected]> wrote:
>
> I have been reviewing various Stack Overflow and other queries regarding the
> use of records, and in particular the compact constructor.
>
> The compact constructor was intended to support a model where the constructor
> body minimally mutates the _constructor arguments_ (if they need to be
> normalized, defaulted, or clamped), which are then automatically committed to
> the fields on successful exit:
>
> record Rational(int num, int denom) {
> Rational {
> int gcd = gcd(num, denom);
> num /= gcd;
> denom /= gcd;
> }
> }
>
> However, developers do not seem to be getting this, and they are instead
> appealing to the old idiom:
>
> record Rational(int num, int denom) {
> Rational {
> int gcd = gcd(num, denom);
> this.num = num / gcd;
> this.denom = denom / gcd;
> }
> }
>
> . . .
>
> So, the question I want to ask is: should we simply _ban_ reads and writes to
> `this.x` in the body of a compact constructor, and let the auto mechanism
> take care of it, so there is no confusion about mixing initialization modes,
> the correct idiom, or reading possibly uninitialized fields? (If we did, we
> would probabably extend this to `this`-bound fields in the future, should
> that feature come to pass.)
Not a bad idea, but here are two and a half alternatives we could consider:
(1) Simply ban use of “this” within a compact constructor. This might seem
like overkill, but it is very easy to explain: the keyword “this” is not
available in a compact constructor, period. Because the argument names shadow
the field names, you don’t have access to the fields at all in a compact
constructor. If you don’t like it, write a non-compact constructor.
(2) Change the model so that the constructor arguments are committed to the
fields _before_ executing the body of a compact constructor, then for each
argument and corresponding field use this assignment analysis to possibly take
additional action on exit:
if the argument is definitely not assigned in the body of the compact
constructor
take no action on exit
else if the corresponding field is definitely not assigned in the body
of the compact constructor
assign the argument to its corresponding field on exit
else compile-time error
This rule is intended to allow the programmer to use either style safely.
(2a) Same as (2), but apply it on a bulk basis rather than a per-argument basis:
if all the arguments are definitely not assigned in the body of the
compact constructor
take no action on exit
else if all the corresponding fields are definitely not assigned in the
body of the compact constructor
assign all the arguments to their corresponding fields on exit
else compile-time error
This rule would further require the programmer to adopt the same style
uniformly for all arguments.
All of these suggestions depend on compile-time analysis to eliminate redundant
assignments.
—Guy