Summary
Among the more popular features of languages that support closures is the ability to loop over collections using what Neil Gafter describes as internal iterators. In a recent blog post, Gafter asks whether Java should have a similar facility.
Advertisement
Developers new to languages with full closures support, such as Ruby, are often pleasantly surprised at the natural syntax such languages provide to iterate through a collection. An example of such iteration syntax is collection.each in Ruby, for instance.
In a recent blog post, Internal Versus External Iterators, Neal Gafter asks if Java should have a similar facility as well. The question is a subtle reference to Gafter's proposal to add closures to the Java language, since closures would make such iterations easier to implement in Java.
Gafter contrasts internal and external iterators based on a definition given in the "Gang of Four's" book on design patterns:
Clients that use an external iterator must advance the traversal and request the next element explicitly from the iterator. In contrast, the client hands an internal iterator an operation to perform, and the iterator applies that operation to every element in the aggregate.
Gafter goes on to say that:
Languages with well-integrated support for closures (such as Scala, Smalltalk, and Ruby) usually provide support for looping over their collections using internal iterators—they are, after all, easier to use in most cases—while other object-oriented languages (such as C++, Java, and C#) tend to use external iterators. Without well-integrated language support for closures, internal iterators would be too painful to use effectively.
For that reason, the Java collection framework uses external iterators. But once we have closures in the language, wouldn't it be worth reversing that decision?
Gafter provides his answer in his blog post. But what do you think: Would you welcome internal iterators in Java?
I would certainly like internal iterators, because it would save me lots of typing.
But Java could have internal iterators as is, using anonymous classes. Anonymous classes are not as easy to use as functions, but there are there, so it is a shame not to use them.
In a project that I had to write many for loops, I wrote a small utility class and an interface which allowed me to loop using an anonymous class. Granted, it was not as efficient as using iterators, but it quickly allowed me to finish what I was writing at the time.
By the way, the lack of any form of closure is what makes C++'s "for_each" so difficult to use.
The thing that you get with an internal iterator that you do not with an external iterator is that you can control resources and do other things that are scoped around the entire iteration in the container object.
The easiest example of this flaw in an external iterator are with 'synchronized collections'. There is no way for the synchronized collection to lock during iteration and it is something that must be done. It is left to the code doing the iteration to manage this.
Another good example is the ResultSet in JDBC. One of the most common and serious errors I see is not cleaning up after queries. I've written an internal iterator for JDBC (plus other things) to eliminate this flaw.
As Achilleas points out, you can do this now in Java but I think closures or even just function pointers would make this idiom much less burdensome in Java.
> I would certainly like internal iterators, because it > would save me lots of typing. > > But Java could have internal iterators as is, using > anonymous classes. Anonymous classes are not as easy to > use as functions, but there are there, so it is a shame > not to use them. > The problem of anonymous classes is that the only part of the outer (lexical) scope they're able to see are the variables declared as final, which makes them... quite annoying to work with.
Not to mention, of course, the verbosity involved in the genericity since Java has no type inference.
Internal iterators plus closures are swell. The Java programmer today can enjoy all this goodness by picking up Groovy script programming. Even existing JSE classes will have methods such as each() and find() added on to them and are accessible for use from Groovy code. (Yes, the standard JSE classes are significantly enhanced to better support various Groovy idioms.)
However, I will register one mild complaint regarding internal iterators.
It's the business of wanting to prematurely terminate iteration.
In a C/C++/C#/Java loop iteration construct, one can use the break keyword to bail out of iteration - or in some cases just use the return keyword to bail out of the loop and exit the containing function/method with a determined result.
However, with internal iteration there is not a language construct mechanism - other than the brute force technique of throwing an exception - to prematurely terminate iteration. Instead, typically some sort of programming convention is defined that has to be adhered to. Usually that will be something along the lines of: If the closure returns true then iteration will be continued, but otherwise iteration will be halted.
Because closures can reference variables in an outer scope, such variables can be set by the closure with the "result" of the iteration.
Hence this convention approach is a workable technique.
I would just prefer to have a language construct for doing this that would not depend on programming convention.
So if this closures and internal iteration are added to Java, what about addressing this too?
Roger Voss wrote: > Internal iterators plus closures are swell. The Java > programmer today can enjoy all this goodness by picking up > Groovy script programming. Even existing JSE classes will > have methods such as each() and find() added on to them > and are accessible for use from Groovy code. (Yes, the > standard JSE classes are significantly enhanced to better > support various Groovy idioms.) > > However, I will register one mild complaint regarding > internal iterators. > > It's the business of wanting to prematurely terminate > iteration.
Your complaint about Groovy is noted and I agree. Fortunately neither Ruby nor Smalltalk nor Scala, nor the proposed closures extension for Java, suffer from this problem.
Specifically, in the Java version you can define a looping API that uses closures and the caller can use break and continue to control the flow of the loop. If some enclosing statement is labeled then you can break from that enclosing statement from within the loop. And you can use the return statement to return from the enclosing method.
> How is an Internal Iterator different from the Java 5 > For-Each construct?
I'm not sure I understand the question. The for(:) loop in Java5+ is just syntactic sugar that is equivalent to 'classic' loops over Iterators or arrays.