Equality

John Rose john.r.rose at oracle.com
Mon Dec 21 22:33:57 UTC 2015


On Dec 21, 2015, at 8:50 AM, Doug Lea <dl at cs.oswego.edu> wrote:
> 
> On 12/19/2015 05:20 PM, Brian Goetz wrote:
> 
>>> Right. I agree that the signature must compatibly change,
>>> but not necessarily that anything else does.
>> 
>> OK, we're on the same page.
> 
> Where I think this page says that interfaces with existing methods
> accepting Object args can in principle be anyfied without strictly
> requiring (but usually strongly encouraging) implementation class rework.
> There is a way to enable/translate analogs of Object methods,
> in particular equals().

I think we can do this.  There seem to be more than enough tools
at our disposal:  Ability to define static intrinsics as needed, freedom
to factor tricky code into default methods on interfaces or shared
supers (Object, ValueType), reflection (as a last resort), right to
appeal to lifted value semantics on auto-boxes, close correspondence
between generic any-fied code and specialized code.

(It would be inefficient at this point to work out all the implementation
details over email, as Brian notes.  That work is best done by prototyping.
So I'm holding back for now.)

> We wouldn't normally recommend blanket anyfication of interfaces,
> but Collections is the main one that everyone hopes will be somehow
> doable.

Ability to retrofit is a big goal for us, of course.

> The full story on this has a few more quirks though.
> It gets uncomfortable to cope with synchronized(obj),
> Object.wait, and Object.notify: Semantically, synchronized(val)
> and notify would be no-ops, and wait would block forever.
> Which would be OK, because no sensible general-purpose implementation
> of say, collection.contains would use any of these.

Yes.  Those semantics are appropriate for objects which
are immutable, for which the "write lock" will never become
available.

> And, as John almost noted, compareTo/Comparable needs
> treatment similar to my hybrid version of equals.


Two events like that certainly call for generalization.
Algebraists will be eager to suggest other any-fied relations,
so we want to support open-ended extension mechanisms.
This is one reason value types are envisioned to interoperate
with interfaces.

On Dec 21, 2015, at 9:13 AM, Brian Goetz <brian.goetz at oracle.com> wrote:
> 
> This is what I was getting at above, with "let's treat the implementation part of the problem separately."  There are a pile of idioms that show up in this kind of code whose semantics gets fuzzy when a type variable straddles references and values -- comparison to null, comparison to other objects (particularly 'this', which shows up in AbstractList.toString), synchronization, assignment to null, instanceof/cast, array creation.)

Add reflection to that list.  Also auto-boxing (which happens
when you cross over to Object).  As I said above, I'm very
optimistic that we can shape the details of these things so
that they are quite useful.  For me the most important guiding
principle is lifting all value semantics to value boxes, while
allowing those boxes to be "heisenboxes" (value-based,
aggressively identity-agnostic).  Those rules usually assign
workable semantics for reference-like operations on
values ("as if boxed").  The actual physical cost of boxing
can be waved away, either by saying "the JIT can optimize
it" or (more aggressively) by lowering the semantics into
the value bytecodes.  In both cases, the source code looks
the same, as if there is autoboxing happening wherever
needed, but the user doesn't need to care where.

> My initial porting exercise of Collections leads me to conclude that the tools needed for migrating the APIs and the tools needed for migrating the code are mostly decoupled.  Since the API changes are more visible, I thought it sensible to start there.
> 
> > It gets uncomfortable to cope with synchronized(obj),
> > Object.wait, and Object.notify: Semantically, synchronized(val)
> > and notify would be no-ops, and wait would block forever.
> 
> This is one approach (the "permanently locked" object approach that John described in an earlier Value Objects proposal), but there are others. Let's come back to this.

(The perma-lock semantics works nicely for frozen arrays.
You want to be able to lock a frozen array very quickly
in order to read it safely, if you are processing a mix of
frozen and under-lock-mutable arrays.  But a fail-fast
semantics is friendlier for other use cases, where we
want to deprecate collections that stupidly lock on their
elements.  This deserves another thread.  My important
point right now is optimism:  We seem to have more
than enough tactics to create a decent design.)

— John


More information about the valhalla-spec-experts mailing list