On May 12, 2018, at 7:34 AM, Brian Goetz <brian.go...@oracle.com> wrote:
> 
> I get that.  What I’m saying is: boxes have a place in the user model.  We 
> may hate them, but without them, we likely find ourselves “boxed” into a 
> corner.  So I don’t want them to be a library convention; I want them to be 
> understood by, say, asType().  Otherwise we’re playing whack-a-mole.  

I don't fully understand the point you make by "a library convention".  Maybe 
"only a
library convention unknown to the rest of the stack"?  The existing box types 
are
a library convention.  It's even an irregular one (int vs. Integer).   The JLS 
recognizes
them (in the box/unbox rules).  Following the JLS, so do asType, core 
reflection,
etc.

Since value types "code like a class" there are new moves for making library
conventions unavailable to primitive types, and adding an interface super seems
to be a better move, for value types, than the companion type pattern we must
use for int/Integer.

Further, we can meet many of the requirements met by the companion class pattern
by using the generic-super pattern (V <: ValueRef<V>) in the case of value 
types.

One requirement *not* met by using the generic-super pattern is run-time 
reification
of the box types, since before erasure ValueRef<Complex> and ValueRef<Point>
are different types, but to the VM they are the same type.  But I don't think 
that's a
deal-killer.  Maybe you see a problem with the erasure that I don't?

Specifically:  Do we really need a VT version of the reified wrapper type 
Integer?
That's what I'm trying to question here, at the risk of playing whack-a-mole.  
There
is serious money to be saved if we can decide the companion class isn't needed
in the case of value types, even if it is necessary scaffolding for non-L-types.

It seems to me that most or all of the machinery in reflection and method 
handles
and the JLS for special-casing the companion classes exists to hoist primitives
into the L-descriptor world.  When the hoisting occurs to a wrapper class, many
use cases go straight up to Object itself (or to another super of a wrapper).
Others stay on the wrapper just to make a method call like toString or hashCode.
Since value types are already classes with methods, and already are 
L-descriptors,
it follows that they don't need wrapper types very often.

Expressing nullity is one of those residual use cases; we know it happens 
sometimes
but the JVM needs help calling it out as a special case.  I claim we don't need 
a fully
differentiated, runtime-reified wrapper type like Integer to handle those 
occasional
special cases.  In the JVM we just need a way to process the nullable VT 
instance as
an Object or an interface.  In the language an erasable static type like 
ValueRef<V>
works as well as a fully reified companion type like Integer.

How far should language go in healing the gap between the int/Integer pattern 
and
the VT/VR<VT> pattern?  Probably not too far until we are ready to fully unify 
the
primitives with values.  But there are simple things we could do that might 
help,
like making a new notation like C.BOX that connects the various types in new 
ways.

— John

Reply via email to