This is not just about lambda expression; it's about all poly expressions that require target typing.
One thing for sure is that this is not an oversight; the case was considered and rejected.
To quote an early spec :
http://cr.openjdk.java.net/~dlsmith/jsr335-0.9.3/D.html
Deciding what contexts are allowed to support poly expressions is driven in large part by the practical need for such features:
The expression in an enhanced for loop is not in a poly context because, as the construct is currently defined, it is as if the expression were a receiver: exp.iterator()
(or, in the array case, exp[i]
). It is plausible that an Iterator could be wrapped as an Iterable in a for loop via a lambda expression (for (String s : () -> stringIterator)
), but this doesn't mesh very well with the semantics of Iterable.
My take is that, each invocation of Iterable.iterator()
must return a new, independent iterator, positioned at the beginning. Yet, the lambda expression in the example (and in your example) returns the same iterator. This does not conform to the semantics of Iterable
.
In any case, it seems unnecessary work to support target typing in for-each loop. If you already have the iterator, you can simply do
iterator.forEachRemaining( element->{ ... } )
Or if you prefer old-school
while(iterator.hasNext()) {
Foo elment = iterator.next();
Neither are too bad; it's not worth complicating the language spec even more. (If we do want for-each to provide target typing, remember it needs to work for other poly expressions as well, like ?:
; then for-each can become too difficult to understand in some cases. And in general, there are two possible target types, Iterable<? extends X> | X[]
, which is very difficult for the type inference system.)
The for-each construct could be considered a syntax sugar because lambda wasn't available. If the language already has lambda expression, it is really unnecessary to have a special language construct to support for-each; it can be done by library APIs.