Migrating methods in Collections
Ron Pressler
ron at paralleluniverse.co
Mon Dec 21 20:50:21 UTC 2015
> On Dec 21, 2015, at 8:03 PM, Brian Goetz <brian.goetz at oracle.com> wrote:
> > I think people would be pretty ticked off if Map.get() just went away.
> I think the response would be: "Those idiots decided to change their
> libraries for their own reasons, I have no intention of ever
> specializing my Map, and yet I have to change my code anyway."
>
But those same people would also consume an API which returns a List<int> and then find those same methods gone anyway.
Although my suggestion would probably require a tool (a javac plugin?) to migrate sources, though. Go has “go fix”, but Java has had such a tool for a long time
(I think James Gosling worked on it). I know I’m making my suggestion sound even scarier, but I think it beats adding a type system trick for the purpose of source compatibility (more on that later).
> Secondarily, while we might plan to do this to Collections in version N,
> other generic libraries (including other JDK libraries) might wait until
> N+3 to anyfy their own. Realistically this means we'd be forced to
> expose whatever versioning mechanism we use here for general use --
> which seems at least as potentially confusing (and open to misuse) as
> partial methods.
>
I don’t know if it would be as confusing (I don’t think it would), but it may possibly also be used to solve the 64-bit index problem.
> While a method-grained versioning mechanism seems like
> it might solve a lot of problems (for example, we wouldn't have needed
> to do default methods), so far, we've not seen any satisfactory theory
> that we'd want to consider building on -- there have been many attempts
> in the academic literature but I think method versioning in object
> oriented systems is still an unsolved problem. So I'm wary this could
> degenerate into something far worse than partial methods -- a bad
> versioning system.
>
Default methods were also necessary for binary compatibility. I’m talking of something much simpler (like @AvailableUpTo(9)).
> Now, I don't want to devolve into premature syntax bikeshedding, but my
> point is: I don't think the it is the concept that is fundamentally
> confusing, its just that we will (in addition to convincing ourselves
> that the model is sound, which is the task currently in front of us)
> then additionally have to fit it into a syntactic expression that makes
> sense to Java users. (Coming up with a good syntactic form is also
> hard, so I want to first ensure we have a sound theoretical model before
> taking on unnecessary additional work.)
>
Maybe. But partial methods are a clever deprecation mechanism that’s built into the type system. Not that I categorically oppose type-system cleverness (superation seems great), but source compatibility — which Java doesn’t always preserve and has a good mechanism to manage anyway — doesn’t seem like a good enough reason.
>> >
>
>
> Partial methods also allow you to do this:
>
>
> interface List<any T> {
> <where T=int> default long sum() { ... }
> }
>
>
> which is not strictly related to migration. (Personally, I don't love
> this as a feature, because it's weaker than it first appears (think:
> "The Expression Problem"), and when you try to shore up these weaknesses
> with a more powerful slicing mechanism like <where T extends Numeric> it
> starts to get more complex
>
Exactly.
> -- but this form of partial method is also
> part of the current best approach we've got for being able to replace
> IntStream with Stream<int>, which is easier in some ways, and harder in
> others, than Collections.)
>
Is the goal to somehow make IntStream into Stream<int> or to deprecate IntStream? If the latter, I also see no reason why sum (but not other sensible operations) must be part of Stream<int>. In any event, a more general solution would be extension methods (I am not proposing we add those).
>
>
> However (picking up the above syntactic form), would you find these
> signatures terribly confusing?
>
>
> interface Stream<any T> {
> ...
> int sum(Stream<int> this);
> long sum(Stream<long> this);
> double sum(Stream<double> this);
> }
>
What about other numeric types? Maybe
BigInteger sum (Stream<BigInteger> this)
too? And what if users would be able to add their own numeric value types? It’s a weird way to add what are essentially extension methods, and on the wrong side of the expression problem as you noted. If, OTOH, we’d have a “numeric” interface on value types and integers (as I think John alluded to), that might make things better.
Also, it’s not so much a question of confusion as of “does it fit with the feel of Java?”
Ron
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/valhalla-spec-experts/attachments/20151221/af61c764/attachment-0001.html>
More information about the valhalla-spec-experts
mailing list