Should Stream be covariant? (original) (raw)
Brian Goetz brian.goetz at oracle.com
Wed Jan 30 12:55:47 PST 2013
- Previous message: Should Stream be covariant?
- Next message: Should Stream be covariant?
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Of course it is possible to remove the invariant BinaryOperator -- it could be replaced with
BiFunction<? super T, ? super T, ? extends T>
Clearly that would be less convenient in some cases, and would have some cost in API readability, since everyone knows what a BinaryOperator is but one has to read more carefully to figure out what the BiFunction is supposed to do.
So I'll turn your question around to you: what benefits would we get from doing so, that would make it worth suffering the consequences of the above?
On 1/30/2013 3:32 PM, Ali Lahijani wrote:
As a mental experiment, I tried to create a "constructive proof" that Stream is covariant in the variable T. My basic idea is that if it is covariant, it should be possible to elevate an expression of type Stream<? extends T> to an expression of type Stream in a suitable "mechanical" fashion. So I tried to implemented a function
public static Stream elevate(Stream<? extends T> delegate)... To implement the above method, one of course first needs to prove that Spliterator, Iterator and Optional are covariant in T. But they are quite straightforward. public static Optional elevate(Optional<? extends T> delegate)... public static Iterator elevate(Iterator<? extends T> delegate)... public static Spliterator elevate(Spliterator<? extends T> delegate)... The result of the experiment is pasted below. Almost all methods pass the test, which, I suppose, means that the Stream API has an exceptionally clean design. (It is worth mentioning that not all previous versions of Stream passed the same test so smoothly.) But as the compiler will tell you, there is a problem with two methods, both cases because they use BinaryOperator: public T reduce(T identity, BinaryOperator reducer); public Optional reduce(BinaryOperator reducer); BinaryOperator is invariant in X, so passing T to BinaryOperator removes covariance of Stream. The first method is not needed, it is just a sugar around the third from of reduce which takes three parameters: public T reduce(T identity, BinaryOperator reducer) { return reduce(identity, reducer, reducer); } But to be able to emulate the second form, reduce(BinaryOperator), there should be a method to decompose a Stream as a head/tail pair. Given that facility, one can emulate reduce(reducer) as tail.reduce(head, reducer, reducer). So here is my question: is it possible that the non-covariant reduce methods be removed, and a method for head/tail decomposition is added instead? Best Ali
- Previous message: Should Stream be covariant?
- Next message: Should Stream be covariant?
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the lambda-libs-spec-observers mailing list