Proposal: Accepting a subclass as an element type in a for loop

Derek Foster vapor1 at teleport.com
Fri Apr 3 01:15:25 PDT 2009


I was leaning somewhat on the side of thinking this would be a nice feature (it is, at least, an elegant one), but I think that Reiner's arguments have convinced me otherwise.

The example of the filtering method, in particular, shows that working around this is quite easy. Given that the need for this actually comes up pretty rarely in my experience (I have only ever wanted this once, that I can recall, and it was both easy and intuitive to work around in a manner somewhat similar to but less general than Reiner's suggestion), I think I have come to the conclusion that despite its elegance, this probably isn't worth adding to the language.

Derek



-----Original Message-----
>From: Reinier Zwitserloot <reinier at zwitserloot.com>
>Sent: Mar 31, 2009 11:16 AM
>To: Jean-Louis Ardoint <jlardoint at ilog.fr>
>Cc: coin-dev at openjdk.java.net
>Subject: Re: Proposal: Accepting a subclass as an element type in a for loop
>
>Why is this worthy of a language change? It's very niche.
>
>You can solve your problem by writing 1 method, like so:
>
>for ( Rectangle r : MyUtilityClass.filterOnType(shapes,  
>Rectangle.class) ) {
>    drawRectangle(r);
>}
>
>
>with:
>
>public class MyUtilityClass {
>     public static <A, B> List<B> filterOnType(Iterable<? extends A>  
>in, Class<B> outType) {
>         List<B> list = new ArrayList<B>();
>         for ( A a : in )
>             if ( outType.isInstance(a) ) list.add(outType.cast(a));
>         return list;
>}
>
>
>
>Even if you disregard for a moment that if you add this, I've got  
>about a gazillion other niche things that have about as many use cases  
>and are about as easy to solve with a library for coin,your proposal  
>has omitted a rather serious issue:
>
>What would you do if you have something like:
>
>List<Set<Number>> foo = someMethodCall();
>for ( Set<Double> set : foo ) {
>    // You can't do this in java.
>}
>
>
>
>  --Reinier Zwitserloot
>
>
>
>On Mar 31, 2009, at 14:55, Jean-Louis Ardoint wrote:
>
>> I'm maybe a bit too late. Here's my proposal anyway.
>>
>>
>>
>> -- Jean-Louis Ardoint
>>
>>
>>
>> Accepting a subclass as an element type in a for loop
>>
>>
>>
>> AUTHOR(S): Jean-Louis Ardoint
>>
>>
>>
>> OVERVIEW
>>
>>
>>
>> FEATURE SUMMARY
>>
>>
>>
>> Add a filtering and downcast capability to the enhanced for statement
>> (a.k.a for each).
>>
>>
>>
>> MAJOR ADVANTAGE
>>
>>
>>
>> It should reduce the number of lines of code and depth of nesting in
>> loops. The resulting code would be more readable that what is done
>> currently to achieve the same goal. The meaning of such a loop is  
>> quite
>> obvious.
>>
>>
>>
>> MAJOR BENEFIT
>>
>>
>>
>> Better readability and expressiveness.
>>
>>
>>
>> MAJOR DISADVANTAGE
>>
>>
>>
>> More complexity in the compiler to generate a little bit more  
>> bytecode.
>>
>>
>>
>> ALTERNATIVE
>>
>>
>>
>> You can currently the same thing, yet it means adding an extra if
>> statement and an intermediate variable to be cast.
>>
>>
>>
>> EXAMPLES
>>
>>
>>
>> Here is a small not very interesting example of such a enhanced for
>> loop:
>>
>>
>>
>> Shape[] shapes = ...;
>>
>> for (Shape s : shapes)
>>
>>      drawShape(s);
>>
>>
>>
>> If for a reason you would need to draw only the rectangles, you would
>> need to write:
>>
>>
>>
>> for (Shape s : shapes) {
>>
>>  if (s instanceof Rectangle)
>>
>>    drawRectangle((Rectangle)s);
>>
>> }
>>
>>
>>
>> This is not very aesthetic. If only the for loop would directly  
>> accept a
>> subclass as the element type and do the type checking and downcast, we
>> could be able to write:
>>
>>
>>
>> for (Rectangle r : shapes)
>>
>>  drawRectangle(r);
>>
>>
>>
>> Note that there is a subtlety w.r.t. the handling of nulls. See
>> Compilation below for more details
>>
>>
>>
>> DETAILS
>>
>>
>>
>> SPECIFICATION:
>>
>>
>>
>> The grammar is unchanged. The equivalence between an enhanced for loop
>> and a regular for loop has to be changed in JLS 14.14.2.
>>
>> COMPILATION:
>>
>>
>>
>> The way enhanced loop are translated into bytecode would change
>> depending on whether the loop variable type is a subclass of the
>> iterable or array element type.
>>
>> If the loop variable type is a subclass, then the loop is equivalent  
>> to:
>>
>>
>>
>> For an expression returning Iterable<C>:
>>
>> Iterable<C> cs...
>>
>> for (I #i = cs.iterator(); #i.hasNext(); ) {
>>
>>  C #c = #i.next();
>>
>>  if (#c == null || #c instanceof D) {
>>
>>    D d = (C)#c;
>>
>>    ...
>>
>>  }
>>
>> }
>>
>>
>>
>> For an array:
>>
>>
>>
>> C[] ca...
>>
>> for (int i = 0; i < ca.length; i++) {
>>
>>  C #c = ca[i];
>>
>>  if (#c == null || #c instanceof D) {
>>
>>    D d = (C)#c;
>>
>>    ...
>>
>>  }
>>
>> }
>>
>>
>>
>> Note that we need to test against null to keep the same behavior as  
>> the
>> regular enhanced for loop.
>>
>>
>>
>> TESTING:
>>
>>
>>
>> This feature can be tested in the same way the enhanced for loop is
>> tested.
>>
>>
>>
>>
>>
>> LIBRARY SUPPORT:
>>
>>
>>
>> There is no need for library support.
>>
>>
>>
>>
>>
>> REFLECTIVE APIS:
>>
>>
>>
>> No updates to the reflection APIs are needed.
>>
>>
>>
>>
>>
>> OTHER CHANGES:
>>
>>
>>
>> No other changes are needed.
>>
>>
>>
>>
>>
>> MIGRATION:
>>
>>
>>
>> Migration of existing enhanced for loop can be done if one desires so.
>>
>>
>>
>> COMPATIBILITY
>>
>>
>>
>>
>>
>> BREAKING CHANGES:
>>
>>
>>
>> This feature would not break any existing programs, since the new
>> feature only permits more code to be parsed than before.
>>
>>
>>
>>
>>
>> EXISTING PROGRAMS:
>>
>>
>>
>> Class file format does not change, so existing programs can use class
>> files compiled with the new feature without problems.
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>
>




More information about the coin-dev mailing list