Explicit name for value companion type
Victor Nazarov
asviraspossible at gmail.com
Fri Jul 1 12:01:21 UTC 2022
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-comments/attachments/20220701/dbe40776/attachment.htm>
More information about the valhalla-spec-comments
mailing list