Proposal: Accepting a subclass as an element type in a for loop (original) (raw)

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 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 (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 foo = new ArrayList; foo.add(null);

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

you expect m to be called once with null.

If you write

Collection foo = new ArrayList; 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 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> foo = someMethodCall(); for ( Set set : foo ) { // You can't do this in java. } I don't understand your point. A List<Set> should not contain a Set 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 filterOnType(Iterable<? extends A> in, Class outType) { List list = new ArrayList(); 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> foo = someMethodCall(); for ( Set 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: Iterable 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