valhalla-dev Digest, Vol 6, Issue 3

Brian Goetz brian.goetz at
Fri Dec 26 02:02:21 UTC 2014

> Yes, but having thought further, it would probably be clearest to
> definitively rename the methods & annotate the "legacy compatibility"
> name to generate a bridge method.

Yes, this is the option we refer to as "nuke them from orbit".  We could 
do this -- and have of course considered it -- but we hope to do better.

> At that stage I called the concept "compatible" -- which is perhaps too
> strong, as the specific & exact intent is "any subtype or ancestor of T"
> -- essentially, any inheritance relative that could _potentially_ be
> compatible.
> Now my understanding -- which may or may not be exactly correct -- is
> that remove() and removeAll() signatures were typed wider, to allow for
> clients (with less knowledge of specific type) to remove elements from
> collections created with a more-specific type.
> So the possibility I proposed, was to express this as a type expression.
> For reference types, it would resolve as before;  for value types,
> absent any notion of inheritance, it would just flatten to the value type.
> <CT compatible T> public boolean removeItem (CT item);
> <CT compatible T> public boolean removeAll (Collection<CT> items);
> Of course, syntax is just invented here :)

This is similar to what we're calling "loose override", where a 
signature that is "typed wider" but erasure-equivalent could be 
considered an override when restricted to erased-reference receivers. 
Then the signature of removeAll could really be removeAll(Collection<? 
extends T>), and the legacy erased-ref signature could be considered an 
implementation of that modulo erasure.

> 4)  Combinatorial & Utility-class drawbacks to Layering

All of these are indeed relevant concerns (some of which we have 
reasonable sketches on the whiteboard for), but I think you're still a 
bit obsessed with reducing the syntactic footprint.  At this point, the 
important part is finding the right *model* for things like inheritance 
and membership; when we find the right model, hopefully the syntax works 
itself out.

> There is much code already -- Map.get() -- returning a sentinel for "not
> found". My proposal is to expressly recognize that; and ensure that
> better values than 0 are used.
> My initial proposal was to use -1;  not perfect I agree, but the bulk of
> C library APIs has been happy to do without this number for a very long
> time :) However, I'm happy to revise it to Integer.MIN_VALUE. 'double'
> could use either MIN_VALUE or NaN. 'boolean' will have false, and that's
> the best we can do.

I think you're being a little too quick to accept not-perfect for an 
answer!  I actually think this route is unacceptable -- its just too 
error-prone.  The ship sailed on using the full range of primitives 
values years ago.

> Since efficiency is the main reason to specialize, we shouldn't require
> Map.get()'s single-word return to be "blown out" to two; nor should
> wrapping in Optional be required.
> Unless we're going to drop Map.get() from the API, which we shouldn't, a
> sentinel is proveably the only solution.

See the new-in-8 getOrDefault() method.  This allows clients to pick 
their own, usage-specific sentinel, without forcing a global and 
arbitrary choice of sentinels on all primitive users.  This, combined 
with an optional-bearing version for those who can't pick, should cover 
the waterfront.

The "pick an int and make it the sentinel value" approach (and what do 
we do for the other value types?) is just not good enough.  It's even 
worse that the problems we have with null now, since at least nulls fail 
fast when you try to use them.  WHy would we make this worse?

More information about the valhalla-dev mailing list