> On Apr 24, 2020, at 2:24 PM, Brian Goetz <brian.go...@oracle.com> 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

Reply via email to