Tuesday, 2 January 2007

Closures use cases - looping

The closures proposal for Java 7 continues to progress. But there doesn't seem to be a large list of potential use cases lying about, just a few random examples. I'm going to try and write up some example 'use cases' hopefully to help the debate.

each(Collection)

  Collection[String] coll = ...
  each (String str : coll) {
    // do something with str
  }

This would loop around each entry in the collection exactly as per the enhanced foreach loop.

eachIndexed(Collection)

  Collection[String] coll = ...
  eachIndexed (String str, int index : coll) {
    // do something with str
  }

This would provide a loop (0-based, incrementing by 1) as well as the entry each time around the loop.

eachReversed(List)

  List[String] list = ...
  eachReversed (String str : list) {
    // do something with str
  }

This operation would loop around the list in reverse order.

each(Map)

  Map[String, Integer] map = ...
  each (String key, Integer value : map) {
    // do something with key/value
  }

This loops around each entry in the map, giving the loop the key and value each time around. An indexed version of this method would probably also be needed.

6 comments:

  1. You could use those to provide a convenient way of looping for APIs that provide only an Iterator, not an Iterable, and even ye olde Enumeration.

    Perhaps more importantly, looping for any collection type that doesn't implement Iterable. It's arguable that there are no reasons not to implement Iterable, but it's equally arguable that there *should* be no reason *to* implement it, unless you need to.

    I've written a wrapper a couple of times so that I can use a custom collection with the foreach loop - workable but irritating. Looking forward to the javac prototype.

    ReplyDelete
  2. These are the most trivial use cases. You might also want to consider resource acquisition, UI callbacks, monads, and combinator libraries.

    ReplyDelete
  3. Stephen Colebourne2 January 2007 at 12:18

    Ricky, I agree that Iterator/Enumeration/Iterable variants should all be provided.

    Perhaps we might also have an eachNotNull() which only returns elements that are non-null.

    Slava, the next blog post is already out - it just hasn't been picked up by java.blogs, probably due to jroller.

    ReplyDelete
  4. Why should there be new keywords for closures? That would not be a real closure. The way languages with closures work is that the method will accept a closure and act on it. They are used for callbacks, iterated over lists, event handling, etc.

    The difference in the code above would be something like this:

    List foo.each({String item: System.out.println(item)})

    Or something like this:

    JButton OK.onClicked({System.out.println("OK was clicked");});

    As long as the closure looks like a type, it can be used. For example, the implementation of foo.each:

    void each(Closure c)
    {
    for(String item: this)
    {
    c.perform(item);
    }
    }

    The implementation of onClicked would be:

    void onClicked(Closure c)
    {
    c.perform();
    }

    The interface of a closure would be like this:

    interface Closure
    {
    void perform(...)
    }

    The uses would then be up to the implementors.

    ReplyDelete
  5. Stephen Colebourne2 January 2007 at 16:26

    Berin, I think you've missed a stage in the Java closures debate. What you are reading as keywords are in fact regular closure-receiving methods in exactly the way that you are thinking of them. Its just that the syntax for invoking the method is different (they use static import for example).

    In fact, much of the point of the current Java closures proposal is to enable methods to be added to a library that are used in a manner very similar to a new keyword.

    ReplyDelete
  6. Phah! Java does not need closures.

    ReplyDelete