Closure Time for Java

Someone on our (Java) project team has so fallen for Ruby that he is now trying to force the Java code into Rubyesque patterns. He has found an ally for this in the Commons Collections Closure interface. What he seems to want to do in Java is the equivalent of:

sum = 0
list.each { |item| sum += item.amount; }

The Commons Collections Closure class looks like it will help out here, but it won’t. The following code will not compile, because sum must be declared final; and if you do that, you may no longer modify it inside the closure:

CollectionUtils.forAllDo(items, new Closure() {
    public void execute(Object o) {
        Item item = (Item) o;
        sum += item.amount;
    }
});

But then, Closure was defined with a restriction to begin with. If you add the ability to receive parameters beforehand, like this:

public abstract class MyClosure {
    public Object[] params;
    public MyClosure(Object... params) {
        this.params = params;
    }
    public abstract void execute(Object o);
}

then you can send the ‘outside’ variable, sum, to the closure constructor; so it can be used inside the closure:

Object[] result = forAllDo(items, new MyClosure(sum) {
    public void execute(Object o) {
        Item item = (Item) o;
        params[0] = ((Double) params[0]) + item.amount;
    }
});
sum = (Double) result[0];

The new forAllDo needs to return the closure’s parameters after looping, but is rather straightforward for the rest.

Of course, it’s still a long way from Ruby’s simple syntax. Also I wonder how much patience constructs like these will require from the people that will be maintaining this code. After all, the usual way of doing this in Java is just iterating over the collection’s items. But I guess it’s good to look at your coding habits from another point of view now and then.

2006-01-09. 17 responses.

Comments

  1. As a Ruby lover stuck in Java I would have to agree with you. Trying to shoe-horn closures into Java is bad form. Perhaps he should just try Groovy and get it over with.

    It does go to show just how artificial an abstraction (strongly typed) iteration is though – required only because the absence of closures doesn’t allow the collection implementation to perform the iteration itself.

    Any yes, I still yearn for Smalltalk.

  2. Two other solutions:

    Define an extra interface
    ClosureWithResult that extends Closure to have a
    Object getResult() method.

    Then do

    ClosureWithResult sumClosure = new ClosureWithResult() {
        double sum = 0;
        public void execute(Object o) {
            sum +=  ((Item) o).amount;
        }
        public Object getResult() {
            return new Double(sum);
        }
    }
    CollectionUtils.forAllDo(items, sumClosure);
    itemSum= ((Double)sumClosure.getResult()).doubleValue();
    

    Alternatively, there’s this somewhat nasty litte hack:

    final double[] result = new double[] {0};
    
    CollectionUtils.forAllDo(items, new Closure() {
        public void execute(Object o) {
            Item item = (Item) o;
            result[0] += item.amount;
        }
    });
    itemSum=result[0];
    

    It’s only the array reference that needs to be final – not the contents. But declaring an array just to get around the final requirement is definitely an impediment to understanding

  3. Seems like a problem with CollectionUtils and one which could be solved with generics…

    public class ClosureExample {
        
        public static  R forEach(Collection l,Eacher e) {
            for (T t: l) {
                e.each(t);
            }
            return e.close();
        }
        
        interface Eacher {
            R close();
            void each(T t);
        }
        
        public static void main(String[] args) {
            List l = new ArrayList();
            for (int i = 0; i () {
               int sum = 0;
               public Integer close() {
                   return sum;
               } 
               public void each(Integer i) {
                   sum += i;
               }
            });
            System.out.println("total " + total);
        }
        
    }
    
  4. I played around with this sort of thing too. (transferring-scripting-idioms-to-java.php) My take was to create a set of classes that brought the scripting techniques into Java, so building simple tools would take only a few lines of code. I thought it might appeal to some people in a pure Java environments who didn’t have access to other tools. I never polished the code up enough to share it, but it worked for me at the time.

  5. In jga, the same functionality would be

    UnaryFunctor getAmount = 
            new GetProperty(Item.class, "amount");
    return accumulate(Integer.class, transform(items.iterator(), getAmount));
    
  6. We recently found ourselves running into this so often that we wrote a simple Count class to get round the problem:

    final Count count = Count();
    CollectionUtils.forAllDo(items, new Closure() {
        public void execute(Object o) {
            Item item = (Item) o;
            count.add(item.amount);
        }
    });
    return count.total();
    

    I’d take that over the array hack any day.

  7. You could write it as:

    int sum = new Closure() {
        int sum;
        {
            CollectionUtils.forAllDo(items, this);
        }
        public void execute(Item item) {
            sum += item.amount;
        }
    }.sum;
    

    A hack, but possibly worth it if you do lots of it.

  8. Most of these alternative solutions (thanks!) involve creating an extra class or interface; which is what I hoped to avoid. So I especially like Tom Hawtin’s hack, very clever indeed. And thanks for the link to jga; that looks interesting also.

  9. Bruce Eckel had a similar thread not too long ago about wedging Mixins into java.

    http://www.artima.com/forums/flat.jsp?forum=106&thread=133171

    My reply to that thread will serve equally well for this one… ๐Ÿ™‚

    —–
    Hmm, I don’t like it. It goes against the GrainOfTheLanguage.

    http://www.c2.com/cgi/wiki?GrainOfTheLanguage

    Unfortunately, we can’t use all of our favorite styles, techniques, and tricks in every language. To me, this example smells like a case where, even though we want Mixins, it would be better to just shrug it off and continue to write idiomatic java that everyone understands.

  10. I used to work with the common-functor package for this purpose. It works pretty well – really bringing functional programming to Java. Of course, it’s Java so you need anonymous inner classes everywhere, making your code illegible, and confusing the hell out of your non-functional fellow-programmers. But it’s still cool. Take for example a look at this class: http://jakarta.apache.org/commons/sandbox/functor/apidocs/org/apache/commons/functor/generator/Generator.html

    Rings any bells?

  11. […] One way I have applied the Closure object that I’ve found particularly useful is in building XML documents, but I won’t delve into all the ways that closures can be applied to programming problems here. There are many more knowledgable developers out there who have written on this. This is a tool to keep handy, but obviously isn’t suited for every task, as it does have limitations in the Java environment. […]

  12. […] My search lead me to the Apache Jakarta project, which offers many, many useful tools and libraries. One of these libraries is the Commons Collections. The special thing about this library is that it provides closures to Java through two basic Objects; Closure, and CollectionUtils. I believe that the best way to illustrate is to just give a small example. For this example we only need a few classes. import java.util.List; import org.apache.commons.collections.Closure; import org.apache.commons.collections.CollectionUtils; Say you have a list of Strings and you merely want to print them out. Now, you could do it the standard way through a for loop: for( int i = 0; i < list.size(); i++ ) {     System.out.println( ( String ) list.get( i ) ); } Or, you can introduce a closure: CollectionUtils.forAllDo( list, new Closure() {     public void execute( Object o )     {         System.out.println( o );     } } ); The code may seem verbose when you simply want to print out the values in your list and might be better applied as a method that will print any list. public static void printList( final List list ) {     CollectionUtils.forAllDo( list, new Closure()     {         public void execute( Object o )         {             System.out.println( o );         }     } ); } A more practical example might be the processing of orders from an e-commerce application. We’ll define a closure in our OrderProcessor that saves an Order to the database and logs order number and each of the items included in the order to our server logs using Log4J. We’ll assume that Order, OrderItem, and OrderUtils are classes that we’ve already defined for the sake of brevity. import java.util.List; import org.apache.commons.collections.Closure; import org.apache.commons.collections.CollectionUtils; import org.apache.log4j.Logger;   public class OrderProcessor {     private static Logger logger = Logger.getLogger( OrderProcessor.class );       protected Closure processOrderItem = new Closure()     {         public void execute( Object o )         {              final OrderItem orderItem = ( OrderItem ) o;              logger.info( orderItem );         }     };       protected Closure processOrder = new Closure()     {         public void execute( Object o )         {             final Order order = ( Order ) o;             OrderUtils.saveOrder( order );             logger.info( order.getOrderNumber() );             final List orderItems = order.getOrderItems();             CollectionUtils.forAllDo( orderItems, processOrderItem );         }     };       public void processOrders( final List<Order> orders )     {         CollectionUtils.forAllDo( orders, processOrder );     }       public static void main( String[] args )     {         OrderProcessor orderProcessor = new OrderProcessor();         final List<Order> newOrders = OrderUtils.getNewOrders();         orderProcessor.processOrders( newOrders );     } } The example above is just one way that closures can be used, but note the readability it provides. This leaves the methods to do one thing well, and you can easily change the closure definition without having to go to each method to change the way an order is processed. I think that this helps code readability greatly. Another way I have applied the Closure object that I’ve found particularly useful is in building XML documents. I’ll save that for a later time. I won’t delve into all the ways that closures can be applied to programming problems here. There are many more knowledgable developers out there who have written on this. This is a tool to keep handy, but obviously isn’t suited for every task, as it does have limitations in the Java environment, although there are always workarounds. […]

  13. I posted a closure solution in my one and only blog entry:

    http://cgardner.blogspot.com/2006/03/implementing-typesafe-closures-in-java.html

  14. I just saw this article from the net, and I want to jump in here to say you don’t have to use anonymous inner classes. Just create a new class and place it on the file system like any other. This shouldn’t be such an “evil”, it promotes reusability, and if you think about the idea of closures, that they are very atomic bits of functionality, you’ll realize this is a great thing.

    Also, the Java Commons Collections API can go a bit above inlining hard-coded closures, for instance, the chained closure facility:
    Closure[] closures = { printer, counter, prefixer };
    Closure execute = ClosureUtils.chainedClosure(closures);
    CollectionUtils.forAllDo(somearraylist,execute);

    Good to go ๐Ÿ™‚

    Ideally you could use alot of closures in succession or under custom designations to implement your business rules.

    I do like my Python list comprehensions, but I’m for reusability ๐Ÿ˜‰

    The only thing that has to happen now is for common collections to take it’s api to the generics level, so we avoid the object cast on it’s way in.

    Neils, you are wrong in suggesting that those are the only other options in terms of getting items out of the closure. You can implement any type of retrieving/extra method you might want. Why not as the primitive instead? Just because you’re in Java doens’t mean you *have* to use an object wrapper at every point.

    The key focal point is that you begin to see collections as things to operate on, instead of things to manually loop through, and then suddenly, the world of Java is full of one-liners ๐Ÿ˜‰

  15. Ivan: I totally agree with your conclusion. I’m not completely sure about your solution (to create a new class instead of the anonymous inner class), but I’ll certainly try how it works out. It won’t be one-liners though if you need to get data into and out of the closure…

  16. […] Following up on my recent post on Ruby and Rails’ enterprise-readiness, we might want to rethink any strategies comparing or opposing Ruby with Java. Don’t get me wrong: Ruby is a breeze where Java is a mouldy draught; Ruby is a butterfly where Java is an ostrich; Ruby makes you smile where Java is often a maniacal grin. But also they’re both gusts of air, both have wings, both evoke emotion. Both are object oriented languages, both have classes, and methods, and instance variables, and structured in-code documentation, and closures (more or less), both are pass-by-reference-by-value, both have apis for Lists and Maps and Files and Regexps… The list goes on and on. […]