Loose end: spliterator() and stream() methods on Iterable

Remi Forax forax at univ-mlv.fr
Mon Jun 24 14:41:57 PDT 2013


On 06/24/2013 09:40 PM, Brian Goetz wrote:
> After further thought, I think what this means is that we can move 
> spliterator() up to Iterable, but not stream().  The reason for this 
> is that some classes that implement Iterable<Integer> might prefer 
> that their stream() method return an IntStream, not be forced into a 
> Stream<Integer>.  So putting stream() too high up in the hierarchy 
> forecloses on this.

I agree,
Spliterator.OfInt is a Spliterator but IntStream is not a Stream.

Rémi

>
> On 6/14/2013 3:12 PM, Brian Goetz wrote:
>> In trying to work this one out, I ran into a snag with our test code.
>>
>> We have some test code that looks like:
>>
>> public interface TestData<T, S extends BaseStream<T, S>>
>>          extends Iterable<T> {
>>      S stream();
>>      S parallelStream();
>>      ...
>> }
>>
>> with specializations:
>>
>>      public interface OfRef<T> extends TestData<T, Stream<T>> { }
>>      public interface OfInt extends TestData<Integer, IntStream> { }
>>      ...
>>
>> The idea is that the stream() method on TestData.OfRef returns a
>> Stream<T>, and on a TestData.OfInt it returns an IntStream.  With stream
>> methods on Iterable, this causes a conflict.
>>
>> Of course, I can change my test code.  But it illustrates the danger of
>> adding stuff to "top-level" interfaces like Iterable -- the risk for
>> conflict increases dramatically because so many things implement it.
>>
>> Here, the root cause is that I want stream() to be a type-specific
>> method.  This definitely falls into the "advanced generics tricks"
>> category, but being able to do this definitely reduced a lot of
>> duplication in our code base, and I can't imagine I'm the only one who
>> might want to do it.
>>
>> On 6/10/2013 6:19 PM, Brian Goetz wrote:
>>> This is one that everyone seems in agreement with (in theory) but which
>>> we never get to convergence on.  Given how the API has shaken out, it
>>> seems sensible to:
>>>
>>>   - Add spliterator() to Iterator, with a default implementation of
>>>
>>>     return Spliterators.spliteratorUnknownSize(iterator(), 0)
>>>
>>>   - Move the existing stream() and parallelStream() methods up from
>>> Collection to Iterable, as is (they are implemented entirely in 
>>> terms of
>>> spliterator() and public factories)
>>>
>>>
>>> When this last came up, there was concern that the spec of
>>> Iterable.stream() would be exactly as fuzzy as the spec of
>>> Iterable.iterator().  I think the best we can do is add an
>>> implementation note that if iterator() indeed gives you a fresh 
>>> iterator
>>> every time, then stream() gives you a fresh stream every time, and
>>> otherwise unpredictable results will follow.  It would be nice to
>>> further note that subtypes of Collection are better behaved, but sadly
>>> the spec for iterator() in Collection is no better than in 
>>> Iterator!  We
>>> can further add a "recommendation" to Iterable.iterator() to suggest
>>> that Iterable implementations are encouraged to do this, but 
>>> otherwise I
>>> think this ship has sailed.
>>>
>>>



More information about the lambda-libs-spec-experts mailing list