Of your points, I think this is the controversial one, and it goes straight to "what is the point of primitive classes."

You kind of dismiss optimization, but of course a big part of the point is classes that are more optimizable; if we didn't care about optimization, we wouldn't bother with primitive classes, we'd just say "write classes."

The unfortunate bit is that the reason we're stuck with zeroes as the default value comes from the VM's desire to provide both safety _and_ performance.  Painting with a roller is cheaper than with a brush, but, more importantly, all-zeroes is the only value the JVM can really give while promising that some other OOTA value will never be observed, regardless of races and other timing hazards.

Now, let's talk more about null.  Null is a *reference* that refers to no object.  For a flattened/direct object (P.val), null cannot be in the value set (it's the wrong "kind"), though we can arrange for a primitive to behave like null in various ways.  It's not clear whether this helps or hurts the mental model, since it is distorting what null is.

Really, what this discussion is about is about whether _uninitialized primitive objects_ can be used or not; since T.default is a hidden constructor, we want to know whether that value is safe to use or whether it is merely a tombstone.

We can arrange that x.m NPEs when x == X.default, but that doesn't really mean that x is null.  It means that you've dereferenced something that should have been initialized before dereferencing it.

The alternative approaches are worse, since they involve creating a second null (see John's "No New Nulls" manifesto), which I think we can agree no one will like.

What worries me about this approach is that it muddies what null means, since a P.val is not a reference to anything.

I think we are better off treating this as a discussion about initialization safety, rather than nullity, until we have a clear story of how we want things to behave.





On 6/29/2021 1:54 PM, Kevin Bourrillion wrote:
Among all the use cases for primitive classes, the ones where the default value is non-degenerate and expected are the special cases! We use `Complex` as a go-to example, but if most of what we did with complex numbers was divide them by each other then even this would be dubious. We'd be letting an invalid value masquerade as a valid one when we'd rather it just manifest as `null` and be subject to NPEs.

Reply via email to