Hi,

I see this is already discussed in the "Alternatives" section of the proposal (sorry for not reading this through before asking)...

But I don't quite understand the following part that talks about making IterableOnce a supertype of Iterable:

"However, doing so would require weakening the contract of IterableOnce. To allow Iterable to be a subtype, the semantics of IterableOnce would need to change to allow iteration once and possibly more, instead of the currently proposed at-most-once semantics. Having IterableOnce be a subtype allows the specification to make a much stronger assertion."

Why would that require "weakening the contract of IterableOnce" ? Because if IterableOnce was specified to throw exception on the 2nd and subsequent invocations, some instances (those implementing Iterable) would not respect that?

I see this as less evil than doing the other way around. How many situations will rely on IterableOnce to throw exception vs. how many situations will rely on Iterable to allow multiple invocations?

But I agree with assessment that changing language to retrofit foreach loop to work with a supertype of Iterable (although it seems a backwards compatible change) would be too costly for this feature.

And there are already other similar decisions made in API design of Java. For example Collections framework with immutable vs. mutable collections. This distinction is not even encoded in type(s). But this API was designed from the beginning with that in mind and therefore most code consuming collection types documents how it uses the passed-in collections (whether it only reads from them or also modifies them). Consumers of Iterable(s) did not have that requirement from the beginning. If they had, we would not need a special type to mark the distinction. The specification of Iterable could simply state that: "There are two kinds of Iterable(s) in this world: those that may be iterated only once and those that can be iterated multiple times"...

OTOH, having a separate type for only-once iterables would only help identify instances of them, but would not help in documenting the consumers. Consumers would still have to document this via javadoc. I would not recommend consumers to take parameters of type IterableOnce if IterableOnce was a subtype of Iterable, because they would unnecessarily restrict themselves to consume just the less capable instances.

In addition, introduction of IterableOnce as a subtype of Iterable does not help in (re)specifying the Iterable type. There will be two kinds of Iterable(s) in the new world regardless of that.

There is a benefit in the runtime though. The code can decide what to do with the passed-in Iterable depending on it implementing IterableOnce or not. Much like what RandomAccess interface does to List(s). The code can decide to dump the iterable into a List and iterate the List multiple times if the Iterable implements IterableOnce or do direct multiple iteration on the passed-in Iterable if it doesnt.

Regards, Peter

On 3/6/19 4:50 PM, Peter Levart wrote:
Hi Stuart,

According to Liskov substitution principle:

    Subtype Requirement: Let ϕ ( x ) be a property provable about objects x of type T. Then ϕ ( y ) should be true for objects y of type S where S is a subtype of T.


Let ϕ ( x ) for objects x of type Iterable be: "x.iterator() may be invoked multiple times, each time starting new iteration".

This clearly holds.

Does ϕ ( y ) hold for objects y of type IterableOnce? Clearly not.

In this respect Iterable should be a subtype of IterableOnce and foreach loop should be retrofitted to work with IterableOnce.

What do you think?

Regards, Peter

On 3/1/19 3:43 AM, Stuart Marks wrote:
Hi all,

Please review and comment on this proposal to allow Stream instances to be used in enhanced-for ("for-each") loops.

Abstract

Occasionally it's useful to iterate a Stream using a conventional loop. However, the Stream interface doesn't implement Iterable, and therefore streams cannot be used with the enhanced-for statement. This is a proposal to remedy that situation by introducing a new interface IterableOnce that is a subtype of Iterable, and then retrofitting the Stream interface to implement it. Other JDK classes will also be retrofitted to implement IterableOnce.

Full Proposal:

http://cr.openjdk.java.net/~smarks/reviews/8148917/IterableOnce0.html

Bug report:

    https://bugs.openjdk.java.net/browse/JDK-8148917

Webrev:

    http://cr.openjdk.java.net/~smarks/reviews/8148917/webrev.0/

Note, this changeset isn't ready to push yet. In particular, it has no tests yet. However, the implementation is so simple that I figured I should include it. Comments on the specification wording are also welcome.

Thanks,

s'marks


Reply via email to