I don't understand why we need IterableOnce ? Was: Proposal: JDK-8148917 Enhanced-For Statement Should Allow Streams

Peter Levart peter.levart at gmail.com
Fri Mar 15 07:57:10 UTC 2019


Hi,

On 3/14/19 9:51 PM, Remi Forax wrote:
> yes, i think i prefer this solution, one Iterable to rule them all.
>
> First, it's not in the spirit of the Collection API to multiply the interfaces, by example, we have only one kind of Iterator and not an Iterator and a ReadOnlyIterator even if a lot of iterators doesn't implement remove. It's a central design of the Collection API, reduce the number of interfaces to ease the use even if it means that each interface may have a broader definition. The Collection API design has chosen his side between users and library writers (people that provides implementations) because from the library writer point of view you can not specify exactly the semantics you want.
>
> Then from the user POV, what is point of IterableOnce ? I will not using it as parameter because using Iterable is a super-type (like i will use a List instead of an ArrayList as parameter) and if i using it as return type, codes that call that method can put it in an Iterable, this is exactly what the for-each-loop will do BTW, so it's seems useless.
>
> Also as Peter said, there are already codes in the wild that create an Iterable that can only be iterated once, ASM has such class, if IterableOnce is added to the JDK, i will have people ask me to retrofit the ASM class to use IterableOnce just for the sake of having the right semantics ? So basically by introducing IterableOnce, all codes that were perfectly fine in term of semantics before introducing IterableOnce are now not quite right because they are not implementing the right interface ? Hum, i think i still not get why we need such interface.
>
> Rémi

The IterableOnce really does not have utility as a static type and I 
think it might only confuse some (Should I return IterableOnce here? 
Should I consume IterableOnce here? Many would not get the difference at 
first). So in this respect it would be better that there is no 
IterableOnce. But there is a runtime utility (although a marginal one) 
where the code can take two branches depending on iterable implementing 
IterableOnce or not. Similar to RandomAccess marker interface with 
List(s). So the question is whether this situation would be better 
served by introducing an unrelated marker interface instead of a subtype 
of Iterable? For example:


/**
  * Implementing this interface allows an object to be the target of the 
enhanced
  * {@code for} statement (sometimes called the "for-each loop" statement).
  * <p>
  * There are generally two kinds of {@code Iterable} implementations:
  * <ul>
  * <li>Those that allow
  * multiple calls to {@link #iterator()} each returning new instance 
which can
  * be used for independent iterations over elements. {@link 
java.util.Collection}s
  * are general representatives of this type of {@code Iterable}s.
  * </li>
  * <li>And those that allow only one call to {@link #iterator()}, 
providing a
  * single iteration and throwing {@link IllegalStateException} on 2nd 
and subsequent
  * calls. It is recommended that this kind of implementations also 
implement
  * {@link Once} marker interface to allow code to detect the kind of 
{@code Iterable}
  * during runtime. {@link java.util.stream.Stream} is an example 
implementation
  * of this type of {@code Iterable}.
  * </li>
  * </ul>
  *
  * @param <T> the type of elements returned by the iterator
  * @jls 14.14.2 The enhanced {@code for} statement
  * @since 1.5
  */
public interface Iterable<T> {

     /**
      * Marker interface used by {@code Iterable} implementations to 
indicate that
      * they support only a single call to {@link #iterator()} method 
while 2nd and
      * subsequent calls throw {@link IllegalStateException}. The primary
      * purpose of this interface is to allow generic algorithms to 
alter their
      * behavior if they need multiple passes over elements of {@link 
Iterable}.
      *
      * @since 13
      */
     interface Once {}


What do you think of that?

Regards, Peter



More information about the core-libs-dev mailing list