The idea of implicit vs default
Jonathan F
livedinsquares at gmail.com
Sat Jan 20 22:14:42 UTC 2024
Hi Brian - thanks for the clear response.
This is a nice idea, and it has come around several times in the design
discussions. From a the-system-stops-at-the-source-code perspective, it
seems fine; you declare a constructor to make "the default value", and
arrange that this constructor is only ever called once (during class
preparation, most likely), to initialize the "stamp". Then you use the
stamp to stamp out default values. Easy, right?
Understood, and I remember the debates along these lines. But what I’m
hoping to suggest - maybe it’s simplistic - is to in no way change how the
language/VM implement this feature, but ‘just' describe it differently
without introducing a new concept (‘implicit') to the poor developer.
Eliminating a keyword and an idea.
So my (probably simplistic) reaction is: how visible is the mechanism for
initialising a field or array (to most developers)? Couldn't the language
spec cover its tracks by saying notionally variables are initialised from
Point.default, but the VM has discretion to use a different mechanism, and
the spec would specify integrity invariants etc. that are needed (and in
practice couldn’t be achieved by literally stamping with Point.default). So
the language syntax, and the ‘basic idea’ in the developer’s head, are
simple but with footnotes for experts. Hand-wavy I know, but maybe a spec
description like that is possible, or maybe it would just be distasteful?!
best wishes,
Jonathan Finn
On 20 January 2024 at 20:48:21, Brian Goetz (brian.goetz at oracle.com) wrote:
This is a nice idea, and it has come around several times in the design
discussions. From a the-system-stops-at-the-source-code perspective, it
seems fine; you declare a constructor to make "the default value", and
arrange that this constructor is only ever called once (during class
preparation, most likely), to initialize the "stamp". Then you use the
stamp to stamp out default values. Easy, right?
The only problem with this is that it is on a collision course with VM
physics. Many of the integrity invariants, as well as many optimizations,
are built on the assumption that initialization of a new object or array is
always done with the zero-colored paint roller. If you want it done by
stamps, that means not only do you have a stamp for Point, but you also
need a bigger stamp for everything that has a Point flattened into it, and
you have much more data motion for every object initialization. And
initializing arrays means N individual stampings, rather than just a broad
stroke with the zero roller -- even more data motion. Plus, there is more
room for races, and therefore more work to prevent such races, when
initializing by copying from an exemplar than initializing with bzero. And
given that performance is a primary motivation for value classes, adding
cost to initializing values would really have to pay off big to carry its
weight.
But the problem doesn't stop there, because some value classes simply have
no good default, whether it is a physical zero or not. LocalDate is an
example of such a class.
So after considering this multiple times, our conclusion is that while
maybe it could be done, but even if so, it only solves part of the problem,
and the cost would be unreasonably far out of line with the benefit.
On 1/20/2024 2:43 PM, Jonathan F wrote:
I know the EG have considered pretty much everything (I’ve followed the
forums all along) but I haven’t seen this discussed yet, so here goes.
It seems to me the novel concept of implicit for constructors may not be
necessary, as (IMHO) it depends on the story that’s told about how fields
are initialised. Can’t we say the following instead? For a value class
Point, if it has the implicit constructor it also has a quasi-static field
Point.default (I think that’s still the plan). I want to say this
constructor only has 2 things special about it: it has no body, and it’s
used to initialise Point.default when the class is initialised. Later,
fields and array elements of type Point! are (notionally) initialised to
Point.default, not by calling the constructor, which seems more like
reality and like how other fields are set to null/0. So there’s nothing
implicit about the constructor itself; and the creation of Point.default
isn’t magic either, it’s like the creation of Point.class or enum constants
- ‘just one of those things’ that happens when a class initialises.
If that makes sense, I’d go for the previous constructor syntax public
default Point(). Meaning simply this is the constructor used for
Point.default. Or maybe even public default-0 Point() if it’s called the
‘zero instance’.
As a separate but related idea: assuming the language has Point.default, it
could be better to have syntax like Point!.default for the object, with
Point.default meaning null (as these value classes will effectively have 2
defaults), and in general T.default for any type, e.g. double.default. That
seems useful in itself, but it would also allow the simple explanation that
a field or array element of _any_ type T gets initialised to T.default.
Even if that’s not workable, it would make me uncomfortable if
Point.default is non-null when a Point field actually defaults to null!
best wishes,
JF
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-dev/attachments/20240120/facb7b55/attachment.htm>
More information about the valhalla-dev
mailing list