valhalla-dev Digest, Vol 6, Issue 3
Brian Goetz
brian.goetz at oracle.com
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