Proposal: JDK-8148917 Enhanced-For Statement Should Allow Streams
peter.levart at gmail.com
Thu Mar 7 08:41:14 UTC 2019
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.
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.
>> 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:
>> Bug report:
>> 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
More information about the core-libs-dev