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

Jean-Louis Ardoint jlardoint at ilog.fr
Tue Mar 31 10:20:09 PDT 2009


Ok I understand your point about generics. If you have
List<Set<? extends Number>> foo = someMethodCall();
for ( Set<Double> set : foo ) {
   // You can't do this in java.
 }

I would say you would get a nice error, like what you get if you write 
O instanceof Set<Double>
(it's only a proposal for a small feature, not for generics reification)

About nulls, there is a good reason to keep nulls. For example if you write

Collection<Integer> foo = new ArrayList<Integer>;
foo.add(null);

for (Integer i : foo)
  m(i);

you expect m to be called once with null.

If you write

Collection<Number> foo = new ArrayList<Number>;
foo.add(null);

for (Integer i : foo)
  m(i);

If m doesn't get call with null, it would mean that the behavior of the loop depends on the kind of Iterable that is used. I don't think it makes sense.

So, the behavior I propose is that references to null are accepted, so the behavior of the for is independent of the kind of Iterable that is used. I agree that it could be nice to have a syntax to exclude nulls, but this is not related to my proposal. It could be used with regular enhanced for loops.

A typical use case for the proposed loop is for analyzing lists of things. For example, if you have a list of statements, and you want to build a symbol table, you can do
List<Statement> statements = ...
Map<String, VariableDeclaration> symbolTable = ...
For (VariableDeclaration decl : statements)
  symbolTable.put(decl.getName, decl); // assuming I know there is no null
  
Of course, when you are really doing such things, you'll probably need some other exploration tools, like visitors. Yet when you need just to do some stuff on one kind of objects, it would be handy to have such a loop.

--Jean-Louis Ardoint



-----Original Message-----
From: Reinier Zwitserloot [mailto:reinierz at gmail.com] On Behalf Of Reinier Zwitserloot
Sent: Tuesday, March 31, 2009 5:46 PM
To: Jean-Louis Ardoint
Cc: coin-dev at openjdk.java.net
Subject: Re: Proposal: Accepting a subclass as an element type in a for loop

Mistake in my sample. try List<Set<? extends Number>> as an input  
source.

I'll qualify my 'this is too niche' with: I've never, ever, needed  
that. I can think of many things that follow the same general line of  
thought that I'd also never need. Why is yours so special? Can you  
show some relevant use cases? Why is null included in this one? Only  
because it technically can be cast? If you consider the 'instanceof'  
syntax sugar on its face value, you should NOT include it. Why is  
inclusion preferred? Will there be an alternative syntax if I want to  
exclude null? If not, why is that not a valid use case, but yours is?


Some proposals have obvious use cases. Others dont. I would venture a  
guess that it would be quite useful to prove the merit of the use  
cases  you're trying to solve if you're not absolutely certain you  
fall into the former category.

  --Reinier Zwitserloot



On Mar 31, 2009, at 17:41, Jean-Louis Ardoint wrote:

> You might say that all proposals are very niche, and almost all of  
> them can be solved by writing some code (you may save some time by  
> writing a generic comment ☺).
>
> About
> List<Set<Number>> foo = someMethodCall();
> for ( Set<Double> set : foo ) {
>   // You can't do this in java.
> }
>
> I don't understand your point. A List<Set<Number>> should not  
> contain a Set<Double> if you use generics without tweaks. So what  
> would you expect?
>
> Anyway, thank you for your comments.
>
> --Jean-Louis Ardoint
>
>
>
> ________________________________________
> From: Reinier Zwitserloot [mailto:reinierz at gmail.com] On Behalf Of  
> Reinier Zwitserloot
> Sent: Tuesday, March 31, 2009 5:16 PM
> To: Jean-Louis Ardoint
> 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