On Dec 21, 2015, at 8:50 AM, Doug Lea <[email protected]> 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 <[email protected]> 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
