Fwd: Explicit name for value companion type

Brian Goetz brian.goetz at oracle.com
Fri Jul 1 12:39:03 UTC 2022


Now that the model is settling, the messages in the suggestion box -- 
many of them syntax-driven -- are coming fast and furious now.  Here's 
another.

Summary: "Having to type .val will make users angry; can we please find 
a way to make it the default at least sometimes."

The author goes on to suggest a syntax for naming the value companion 
explicitly, observing that if the user can pick two type names instead 
of deriving the type names from the class name, then they can give a 
better name than X.val (perhaps even "complex") to the value companion 
(and perhaps a worse name to the ref, like ComplexRefDontUseMe, further 
discouraging it.)

Comment: Yes, we know.  We have been trying very, very hard to not let 
the syntax tail wag the model dog.  Getting to the right model is the 
much important thing at this point.  (But, I'll take the flood of 
syntax-driven comments we've gotten lately as an indication that the 
model is mostly there, so that's good.) Whether or not to allow the user 
to choose two names (as we already have for int/Integer) has been 
hanging in the air for a long time, but there are more factors there 
than are immediately obvious.  Let's continue to focus on the model for 
the time being; we'll return to syntax in due time.


-------- Forwarded Message --------
Subject: 	Explicit name for value companion type
Date: 	Fri, 1 Jul 2022 14:01:21 +0200
From: 	Victor Nazarov <asviraspossible at gmail.com>
To: 	valhalla-spec-comments at openjdk.org



Hello dear experts,

I've been following the valhalla list for a number of years already and 
I'm quite happy with the currently proposed model, but as others I'd 
like to raise a concern about making .val a use-site knob instead of a 
declaration site.

I don't think there are a lot of problems, but still I think the gist of 
why the use-site usage of .val introduces distress for people is the 
following.

It's easy to miss .val were it should and there is no immediate 
indication that something is wrong:

When performance is not good enough, you need to profile and look for a 
place to insert .val. Profiling is costly, many people have software 
that can only be realistically profiled in production. So yes it's easy 
to fix in a sense, but it's hard to find where the problem is.

The alternative that people see is that for some types you should 
aggressively go through the code and append .val wherever this type is 
available, just to never ever have a need to profile. I envision that we 
will get annotations, static-analysis and even best practices to 
encourage this. The worst example that I can invent is something like a 
naming convention, so that value classes should always be named with Ref 
suffix:

value class CompexRef {
}

so that all actual usages will become

CompexRef.val v = CompexRef.of(1, 5);

or annotation for static-analysis tool

@AlwaysUseVal
non-atomic value class CompexRef {
}

The introduction of conventions and additional tooling is 
understandable: it's much cheaper to solve this problem like this than 
to profile software on a case by case basis.
I think this is the main issue, even though the performance model is 
adequate and the use-site knob is good to tweak performance, there are 
still cases that can be fixed "once and for all", and people will reach 
to this solution no matter what. And I think language has to accommodate 
for this and not create a new industry of static-analysis tools.

Another similar case is missing initialization. This is not so 
convincing, because we have already become good at fixing NPE and we 
already have good static analysis tools for nullability. But still 
fixing missing initialization for some Complex variable based on catched 
NPE is much, much more costly then having some kind of static-analysis 
that says that Complex should always be initialized to zero. So here 
again there is a solution that can "fix NPE" for some areas without 
going case by case. And some types, like Complex, should probably be 
"just fixed once and for all".

So I think this is it, there are no more overlooked problems, but I 
think the problem stated above is serious enough to make people concerned.

If I go to a solution, then I don't think I have a perfect answer, but 
leaning on "code like a class works like an int mantra" maybe we can 
reuse the concept of "permit" from sealed-interfaces and make value 
companion to be explicitly named, like:

non-atomic value record ComplexRef(int re, int im) 
__permits_value_companion Complex {
}

__value_companion Complex __unboxes ComplexRef {
     static Complex of(int re, int im) {
         return new ComplexRef(re, im);
     }
}

there should be no explicit state and no constructor in the Complex 
value companion, all the state management is performed in normal class 
ComplexRef.

Maybe "__value_companion" should be called "primitive", because it is 
not a class, but something that has a "wrapper" class. We can imagine 
that Integer and int are defined like this:

value class Integer permits-primitive int {
}

primitive int {
}

--
Victor Nazarov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-spec-observers/attachments/20220701/3c8c0adc/attachment-0001.htm>


More information about the valhalla-spec-observers mailing list