You say it jokingly, but we've explored this.  (The exact way you phrase it (the supertype specified to throw if called more than once) means that Iterable can't extend IterableOnce, because then Iterable does not conform to the superclass contract, but there are other ways to stack it.)  It's not completely unworkable, but as you've observed, it's not so clean.

In the JSR-335 EG, we also explored (and rejected, because it felt like the library tail wagging the language dog) the route of adding language support for more kinds of things on the RHS of the for-each loop.

(Zooming out: the main reason this is irritating is the limitations of what you can do in a method like .forEach() vs the foreach loop -- exception transparency, nonlocal return, up-scope local mutation.  Though it is unlikely that we'll have great solutions for these all that soon, so its reasonable to consider library-based solutions in the meantime.)

On 12/11/2018 7:55 AM, Rachel Greenham wrote:
Although I do understand the reasoning (non-repeatability of streams), Stream not implementing Iterable is a minor but frequent annoyance for this precise reason. Using forEach() instead isn't always an option.

Maybe Iterable can have a superinterface IterableOnce with the methods moved up to there, and iterator() specified to throw IllegalStateException if called twice, and which enhanced-for recognises, then Stream can implement that? (Ducks and runs...)

Or enhanced-for can also take Supplier<Iterator>, so we can do 'for (Thing e : stream::iterator)' instead of 'for (Thing e : (Iterable<Thing>)stream::iterator)'

(runs faster...)


Reply via email to