ACCEPTABLE?: List Comprehensions?

Reinier Zwitserloot reinier at
Sat Mar 14 09:15:46 PDT 2009

Ah, list comprehensions. I forgot them on my list. They aren't  
closures, but you can do quite a few closure use-cases with them, and  
are a lot easier to understand. The draft proposal looks good (but is  
incomplete; it doesn't mention any JLS chapters, for example), but  
there's one big issue it doesn't mention: If the list comprehensions  
return Iterables, then the generating expression, as well as the  
filter expressions, are effectively 'closures' and get all the  
complications that stem from this. For example, you would not be able  
to use non-final variables in there, unless we change the rules  
regarding usage of non-finals in 'closures', which involves a  
significant change for the JVM (it has to declare that variable on the  
heap and not on the stack).

Generating the entire list on the spot has none of those issues, and  
turns the entire proposal into syntactic sugar + a new utility class  
in the spirit of Collections and Arrays, named 'Iterables'. That's all.

Joe: If a list comprehension proposal is written that involves  
(extensive) syntax sugar + 1 new class file and nothing else, would  
they have a chance?

Example desugaring:

public List<Integer> findEvensAndAdd(List<Integer> in, int valueToAdd) {
     List<Integer> out = [x + valueToAdd for x : in if x % 2 == 0];
     return out;


public List<Integer> findEvensAndAdd(List<Integer> in, int valueToAdd) {
     List<Integer> $uniqueName = new ArrayList<Integer>();
     for ( int x : in ) {
         if ( !(x % 2 == 0) ) continue;
         $uniqueName.add(x + valueToAdd);
     $uniqueName = Collections.unmodifiableList($uniqueName);
     List<Integer> out = $uniqueName;
     return out;

In other words, a uniquely named list is created, the variable  
declaration + source list is moved straight into a foreach loop  
clause, then the filter statement(s) are all concatenated via if ( ! 
CLAUSE1 || !CLAUSE2 || !CLAUSE3 ) continue, and finally the generator  
expression is used to generate a value, which is added to the uniquely  
named list. Finally, the list is turned into an unmodifiableList to  
avoid having to specify exactly what happens or can't happen when you  
add/remove/change the list.

Definitive assignment follows from this desugaring; any variable read  
out anywhere in the list comprehension (in any of the 3 places where  
they can occur; generator, sources, filters) are presumed to be read  
(and thus need to be guaranteed initialized), any variable set  
anywhere in the list comprehension is presumed to Maybe occur - so  
it's enough to trigger 'final' warnings, but its not enough to  
guarantee initialization. The only exception is the sources list,  
which is like a normal statement (guaranteed to be run, exactly once).

the type of the expression is List<X> where X is the type of the  
generating expression.

  --Reinier Zwitserloot
Like it? Tip it!

More information about the coin-dev mailing list