Lambdas in for-each loops

Peter Levart peter.levart at marand.si
Wed Sep 5 03:52:08 PDT 2012


On Wednesday, September 05, 2012 10:52:22 AM Maurizio Cimadamore wrote:
> On 05/09/12 10:01, Remi Forax wrote:
> > Lambdas require target typing, so we should update the spec/compiler to
> > have target typing everywhere it's needed. So foreach loop should allow
> > target typing (once array are ruled out) and conditional expression
> > should allow target typing too.
> 
> Target type in conditional is already supported.
> 
> What I'm saying is that the rule-out-the-array approach is obvious
> enough when the expression of an enhanced for loop IS a lambda or a
> method reference. If it's a conditional should we pass in Iterable<X>
> regardless of the conditional subexpressions? What if it's something like:
> 
> for (String s : ? new String[] { "" } : new String[] { "" })
> 
> If you pass in the target type in this case you will get a compile-time
> error as String[] is not compatible with Iterable<String>.
> 
> Also, the deliberate simplification of considering the target type to be
> Iterable<X> where X is the variable type, would lead to other problems:

Might be any better for target type to be Iterable<? extends X> instead?

> 
> Iterable<? extends String> ies = ...;
> 
> for (String s : ? ()-> { ... } : ies)
> 
> This would be a compile-time error, as Iterable<#1>, where #1 <: String
> is not compatible with Iterable<String> (the 'supposed' target type).
> However, the following:
> 
> for (String s : ies)
> 
> compiles now.
> 
> The nature of the for-each loop is very peculiar - an attempt to evolve
> it and treat it as any other target-typing context is error-prone at
> best because, as I said, the language works backwards in this particular
> case.

In other words, when foreach loop was designed, the designers did not see 
enough into the future to anticipate that Java might some day need target 
typing in foreach context, although target typing was introduced to Java at 
just the same time (1.5 - generic methods). If they anticipated that, they 
might not have choosen the same syntax for iterating over elements of Iterable 
AND array...

Could compiler in foreach context work in the following way:

for (X x : exp)

1. if X is primitive type, choose target type as X[] and "proceed" to exp, 
end.
2. if X is not primitive then:
  2a. choose Iterable<? extends X> as target type and try to "proceed" to exp;
        if successfull end, else
  2b. choose X[] as target type and try to "proceed" to exp;
        if successfullt end, else
  2c. choose Object[] as target type and try to proceed to exp;
        if successfull report failure from 2b else report failure from 2a

I don't know about compiler internals but "proceed" attempt in the above is 
meant to represent some kind of attribution phase on the clone of the sub-tree 
that represents the "exp" so that the unsuccessfull attribution effects can be 
undone and re-tried with different input...

Hm...

One corner case I can think of now is what should be infered in the following 
example:

<T> T m() { ... }

for (String s : m()) ...

> 
> Maurizio

Regards, Peter



More information about the lambda-dev mailing list