Proposal: Accepting a subclass as an element type in a for loop
Jean-Louis Ardoint
jlardoint at ilog.fr
Tue Mar 31 08:41:20 PDT 2009
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