RFC: Proposing a high level iteration facility based on Collections
I am requesting for comments for an experimental package I developed providing ahigh level facility for iteration on Java 2 Collections.
You can browse the javadoc at http://www.cacs.louisiana.edu/~cxg9789/javautils/ and the code is available for download from http://www.cacs.louisiana.edu/~cxg9789.
Basically, the package provides an interface Task that has a single method job() which is called for every element in a given collection. There are some static methods for using this kind of scheme and iterating over collections. An example would be: Iteration.loop(collection,new Task(){
publicvoid job(Object o){
// do something on o here
}
});
Now you may wonder what is the use of going into this much trouble when I can just get an iterator and do the same thing? Well, creating a class that represents the whole iteration opens a number of new possibilities. You can now have methods and variables exclusive for the specific iteration and reuse it. You can even subclass it for variants. This proved very useful in my application especially when I developed theStringTask class that is available in the same package.
Nevertheless, you can see it for yourself that we've got rid of the iterator and the condition checking that appears in conventional loop constructs. For details you can look at theIteration at http://www.cacs.louisiana.edu/~cxg9789/javautils/edu/ull/cgunay/utils/Iteration.html andStringTask at http://www.cacs.louisiana.edu/~cxg9789/javautils/edu/ull/cgunay/utils/StringTask.html
I was wondering if you Java developers would find such a scheme useful. Thanks for your interest..
This is about "Advanced Language Topics" but nobody seems to take it into account.. Did anybody see it at all when I originally posted it?
This reminds me quite a lot of the apply and fold operators from Haskell.
Which means that your classes would probably be useful when porting an application from Haskell into Java.
I can't think of a situation that I have been in with a Java project where I would have found an obvious use for such a function, though.
In all honesty, I think a foreach operator and an Iterable interface would be of more use overall... with the benefit of being more lightweight and runtime-optimisable.
> This reminds me quite a lot of the apply and fold
> operators from Haskell.
I studied Haskell some time ago.. Can you remind me of what apply and fold operations were?
> I can't think of a situation that I have been in with
> a Java project where I would have found an obvious use
> for such a function, though.
Well, I developed this scheme when I was working a program which depended on list structures and I needed to do different operations on elenets of these lists. I realized I keep on repeating the same pieces of code everywhere in the program, and decided to put them together in a class.
As a more sphisticated example from what's above I can show my StringTask class which is derived from the Task class in the earlier message. The following example creates a string consisting of some information from each element in a collection separated by commas and enclosed in parens.
String inParens = new StringTask("(", ")") {
public void job(Object o) {
super.job(((MyO)o).getSomeResult() + ", ");// Add the string representation of object and a comma
}
}.getString(vector);// Iterate on vector
> In all honesty, I think a foreach operator and
> an Iterable interface would be of more use
> overall... with the benefit of being more lightweight
> and runtime-optimisable.
I've recently heard this same opinion for the foreach keyword from the BeanShell community (A lightweight scripting system based on Java at http://www.beanshell.org ).
I haven't thought at all on being light-weight and run-time optimizable issues. THat's an interesting point I should consider..
> > This reminds me quite a lot of the apply and fold
> > operators from Haskell.
>
> I studied Haskell some time ago.. Can you remind me of
> what apply and fold operations were?
Heh... now I need to remember back...
No I don't, the internet comes to the rescue :-) I was wrong, apply is the simple "function apply" function, the list function of interest was (is) called map.
http://www.cse.unsw.edu.au/~paull/cs1011/hof.html
> As a more sphisticated example from what's above I can
> show my StringTask class which is derived from
> the Task class in the earlier message. The
> following example creates a string consisting of some
> information from each element in a collection
> separated by commas and enclosed in parens.
> > String inParens = new StringTask("(", ")") {
>public void job(Object o) {
> super.job(((MyO)o).getSomeResult() + ", ");
> ");// Add the string representation of object
> and a comma
>}
> }.getString(vector);// Iterate on vector
>
Just as a comment on the design, I would have maneuvered the list of getSomeResult() into an object that knows how to render itself as a String. That may well be using your Iteration feature over the internal list, or other feature as the developer sees fit.
Your iteration is a perfectly valid pattern to iterate over a collection, and one that could be applied in many places in my code. I'm unsure I will migrate to use it, because it tends towards a large number of small objects to perform its function... which sometimes can be a simplification, but in this case can obscure multi-threading issues... spreading a loop over a collection across multiple classes makes it less obvious what is happening to the contents, or what synchronization is required, what locks have been acquired, or what concurrent modifications are possible.
To keep this information in one place, you could use an anonymous inner class, but then you have lost the reusability and succinctness of the iteration, which are two of its largest benefits (Being a high-level function using centralised, tested code being the third, and probably the largest)
> > In all honesty, I think a foreach operator and
> > an Iterable interface would be of more use
> > overall... with the benefit of being more lightweight
> > and runtime-optimisable.
>
> I've recently heard this same opinion for the
> foreach keyword from the BeanShell
> community (A lightweight scripting system based on
> Java at http://www.beanshell.org ).
>
> I haven't thought at all on being light-weight and
> run-time optimizable issues. THat's an interesting
> point I should consider..
Thinking about it, your iteration is at a higher level than foreach... and would benefit from using it if were ever supported by the JVM. They are slightly orthogonal approaches to looping abstraction, foreach being syntactic and your pattern being heuristic.
Hi,
Proposal is not bad I would say. I would say, this is something similar to the JAAS framework. Here every class defined has methods like login, logout and must confirm to an Interface. When such definitions are provided in a set, the methods login or logout or any such method are called on each one of the members in the set. I guess this is what you are trying to achieve.
You can add an additional function of controlling the number of executing threads in ParallelTask. This one I had to code for for I faced certain thread-safety problems with Entrust Java/SSL toolkit.
Anyway not bad for a start. I hope you will get lots of feedback on providing more functionalities.
- Nil
fiontan:
> In all honesty, I think a foreach operator and
> an Iterable interface would be of more use
> overall... with the benefit of being more lightweight
> and runtime-optimisable.
Like C# ;)
Seriously, I have to agree. Having a foreach operator with a common Iteratable interface is the way to go for the very reasons you state (as well as for better usability)... suppose that's why the C# designer[s] chose that path.
> Heh... now I need to remember back...
> No I don't, the internet comes to the rescue :-) I
> was wrong, apply is the simple "function apply"
> function, the list function of interest was (is)
> called map.
>
> http://www.cse.unsw.edu.au/~paull/cs1011/hof.html
This was very helpful. Now I know what you're saying. Actually this may very well be the hidden influence that lead to this system. The map operation also exists in Lisp and Scheme. I remember really liking it when I first learned about it.
My approach isn't exactly the same as neither of map, fold or filter. But I think I can create subclasses of Task which act the same way with these. I will try to do this in the near future.
> Just as a comment on the design, I would have
> maneuvered the list of getSomeResult() into an object
> that knows how to render itself as a String. That may
> well be using your Iteration feature over the internal
> list, or other feature as the developer sees fit.
This point is well taken. Actually my program uses this kind of approach in many places, however I wanted to give a less confusing example here.
> Your iteration is a perfectly valid pattern to iterate
> over a collection, and one that could be
> applied in many places in my code. I'm unsure I
> will migrate to use it, because it tends
> towards a large number of small objects to perform its
> function... which sometimes can be a simplification,
> but in this case can obscure multi-threading issues...
> spreading a loop over a collection across multiple
> classes makes it less obvious what is happening to the
> contents, or what synchronization is required, what
> locks have been acquired, or what concurrent
> modifications are possible.
On the other hand, it might be more secure to have operations on collections in a place as an Iteration class to keep them together. Maybe you already mentioned it in your message. I can understand your concern in using the system, though.
> To keep this information in one place, you could use
> an anonymous inner class, but then you have lost the
> reusability and succinctness of the iteration, which
> are two of its largest benefits (Being a high-level
> function using centralised, tested code being the
> third, and probably the largest)
I started using small inner classes very extensively. Maybe this can alleviate the problem, since they're not anonymous and can be reused. However, there is still a problem using (subclassing) them from outside of the class. I found a way to do this, too. It only works in special situations, though.
Assume you have an inner class:
public class Outer {
class Inner { ... }
}
You can extend this inner class if you have another class extending the Outer:
class NewOuter extends Outer {
class Inner extends Outer.Inner { ... }
}
> Thinking about it, your iteration is at a higher level
> than foreach... and would benefit from using it
> if were ever supported by the JVM. They are slightly
> orthogonal approaches to looping abstraction, foreach
> being syntactic and your pattern being heuristic.
We're in tune here, I'd be interested to use the foreach operator and the Iterable interface as primitives in my system if they will ever be provided in Java. Currently, they are not offering me anything extra, since the Collection interface provides me with what I need.
> My approach isn't exactly the same as neither of map,
> fold or filter. But I think I can create subclasses of
> Task which act the same way with these. I will
> try to do this in the near future.
You should be able to trivially implement map, foldl and filter using your interface... foldr might be more interesting - basically it means the result is built from the end of the list back to the start, and requires either iterating in reverse or using a tail-recursion...public int sum(Iteration iter) {
if (iter.hasNext()) {
return ((Integer) iter.next()).intValue() + sum(iter);
} else {
return 0;
}
}
Just a thought. :-)
> On the other hand, it might be more secure to have
> operations on collections in a place as an
> Iteration class to keep them together. Maybe
> you already mentioned it in your message. I can
> understand your concern in using the system, though.
This is basically just my paranoia in multi-threaded systems. If a collection were shared between threads, then I would need some kind of concurrency guarantee when dealing with its data. In particular, if iterating through the collection I would most likely take a synchronized copy of the collection and then iterate through the local copy in an unsynchronized loop. There's no particular reason why these couldn't be done with your interface except habit, I guess :-)
> I started using small inner classes very extensively.
> Maybe this can alleviate the problem, since they're
> not anonymous and can be reused. However, there is
> still a problem using (subclassing) them from outside
> of the class. I found a way to do this, too. It only
> works in special situations, though.
>
> Assume you have an inner class:
> > public class Outer {
>class Inner { ... }
> }
> You can extend this inner class if you have another
> class extending the Outer:
> > class NewOuter extends Outer {
>class Inner extends Outer.Inner { ... }
> }
If your inner class does not depend on the state of your outer class, then you will certainly benefit from declaring the inner class static...public class Outer {
static class Inner { ... }
}
class NewInner extends Outer.Inner {
}
> We're in tune here, I'd be interested to use the
> foreach operator and the Iterable
> interface as primitives in my system if they will ever
> be provided in Java. Currently, they are not offering
> me anything extra, since the Collection
> interface provides me with what I need.
I guess that's why there isn't much movement over the foreach thing... it offers a concise and intuitive syntax, but not really anything else. Once generics are in the language proper (Java 1.5, I believe), it would be interesting to see if any independent java compilers offers (bytecode-compatible) foreach support.
Hey guys, I proposed the same RFC in another forum. There had been some interesting discussions. Check this thread out from the Water Cooler: http://forum.java.sun.com/thread.jsp?forum=361&thread=251409