Future directions for records (was: Records — Dealing with nullable values)

Brian Goetz brian.goetz at oracle.com
Sun Dec 15 16:34:30 UTC 2019

> Brian, I still think that there is the opportunity to build on
> records, onion-like, to handle bean use cases. 

I have long been assuming so (though, by way of expectation setting, I want to let the current feature settle and get real usage feedback before we dive into future rounds of design.)  

Our hope has always been to find a way to spread the record goodies more generally, in a way that records are, in the end, revealed to be merely a specific configuration of lower-level features.  (In this way, we’re building onion-like towards the center of the onion.)  If there were primitives for “better constructors”, “better equals and hashCode”, and “more streamlined accessor methods”, then there’d be nothing special about records, other than they bundle up these features.  This would be a nice world because then you could take or leave whichever bits benefit you, and if you want the whole package, you still get a nice (syntactically and semantically) way to say it.  Based on preliminary explorations, though, I doubt there is a single unifying factor that ties together all of these; I think these are largely separate primitives.

One obvious example of where we can build is how fields are initialized in constructors; the `this.x = x` boilerplate should be eliminable in most cases, as they are in the compact record constructor, as long as we can provide a mapping between parameters and fields.  (Records win here because there is, by definition, such a mapping between ctor parameters and fields.)  And when we have declarable deconstruction patterns, the reverse boilerplate (x = this.x) will get similar treatment.  

Stepping back, the information that is destroyed in the typical encapsulation story is that there are multiple utterances of the name `x`, but there is no linguistically justifiable means to reason that the field `x` and the constructor parameter `x` and the accessors `getX` and `setX` are referring to the same x, unless a human reads the documentation for the class and concludes this to be the case.  (This sucks, since this is actually the case most of the time, and indeed frameworks make assumptions all the time that getX and setX must be referring to the same abstract property.)  Records reconstruct this, with a big hammer, by forcing all of the protocols (representation, construction, deconstruction, equality, hashing, display) into strict alignment; this is great when it does what we want.  In the general case, we need to find a way to associate that the `x` parameter of the constructor is really talking about the same `x` as the field `x`; this can unlock more of the goodies (“the equals and hashing protocols are derived from the fields x, y, and z”).  

Building in the other onion-direction, another example is one we haven’t done yet: named invocation.  It has been pointed out that records could use named invocation (e.g., new Foo(x: 1, y: 2)), and they could — but we would rather wait until we can have a consistent treatment for all classes. 

All of this is to say, it is likely that records are not the end of this story, but it is likely the rest of the story will be on hold for a while, as we look towards other priorities. 

More information about the amber-dev mailing list