Scope for JEP 468: Derived record creation

Chris Bouchard chris at upliftinglemma.net
Fri Mar 1 00:39:02 UTC 2024


Hi there. I'm new to this mailing list, but I had a similar thought to Swaranga
recently when this JEP was posted on Reddit.

Personally, my primary concern isn't having nice syntax for constructing
records. It's that if we *don't* provide nice syntax for constructing records,
people will be incentivized to hack it in by overloading the new "with" syntax.
For example, consider something like

    record MyRecord(String foo, String bar) {
        MyRecord {
            // We'd prefer to reject nulls entirely, but we'll allow all nulls
            // to have a "blank" object.
            if (allNull(foo, bar))
                return;

            // With that out of the way, validate our *actual* constraints.
            if (anyNull(foo, bar) || foo.length < 1 || bar.length < 1)
                throw MyDomainException();
        }

        public static MyRecord blank() {
            return MyRecord(null, null);
        }
    }

Now I can say

    var value = MyRecord.blank() with {
        bar = "World";
        foo = greeting(bar);
    };

Except that now, because my model didn't have a natural "blank" value, I've
added an *un*natural one in the interest of ergonomics. This "blank" object has
to be a valid record value. And since the with block's variables are all
initialized to null, users can accidentally run into problems with partial
initialization.

    var value = MyRecord.blank() with {
        // Whoops, forgot to initialize bar so it's still null.
        // bar = "World";
        foo = greeting(bar);  // NPE
    }

On the other hand, if we provided an actual way to initialize a fresh record
using this block syntax, we could say that all variables in the block are
unitialized to start and must be assigned before use. And this initial state
wouldn't have to be accepted by the constructor.

People have been asking for keyword parameters in Java for years. Whether or not
this block syntax is what the language designers would choose for keyword
parameters, I think that if we introduce this feature without some way to
construct new instances it will become the de facto syntax. It's just too
tempting.

Thanks for your time and attention,
Chris Bouchard

On Thu Feb 29 23:11:32 UTC 2024, Brian Goetz wrote:
> While such a feature is possible, I am not particularly excited about it
> for several reasons.  If the goal is "I want to construct using named
> instead of position arguments" (which I think is your goal), it's a
> pretty verbose syntax; a better one would be
>
>     new R(a: 1, b: 2)
>
> But that's a much smaller concern.  The bigger one is that I don't think
> the language is improved by having a named parameter mechanism for
> records, but for nothing else (not for instantiating class instances,
> not for invoking methods.)  While it might seem "better than nothing",
> having two different ways to do something, but one of them only works in
> narrow situations, is as likely to be frustrating than beneficial.  If
> the payoff is big enough, then it might be a possibility, but
> "invocation by parameter name" is nowhere near that bar.
>
> Finally, if it works for records but not for classes, it makes it harder
> to refactor from records to classes, since there will be use sites that
> have to be adjusted.
>
> So I think for the time being, the answer is "no", though if we run out
> of things to work on, we might reconsider.
>
> On 2/29/2024 4:34 PM, Swaranga Sarma wrote:
> > The JEP looks really promising. However I am wondering if there will
> > be a separate JEP for creating new records from scratch with similar
> > syntax.
> >
> > The current JEP states that its goals are to enable creating records
> > from an existing record and for that it seems sufficient. But I would
> > also love to be able to create new records from scratch using the same
> > syntax. Something like:
> >
> > var circle = new Circle with {
> >   radius = 0.5f;
> >   center = new Center with {
> >     x = 0;
> >     y = -1;
> >     z = 8;
> >   };
> > };
> >
> > Originally I had asked Brian Goetz about record literals and they
> > seemed like a possibility but withers seem like a more general feature
> > so I am hoping something like this would be supported in the future.
> >
> > Regards
> > Swaranga Sarma


More information about the amber-dev mailing list