Here's the code in idiomatic Java5 syntax:

    public void sample( List<Integer> numbers )
    {
        List<Integer> inverse = new ArrayList<Integer>( numbers.size() );
        for( Integer i : numbers )
        {
            inverse.add( -i.intValue() ) ;
        }

        for( Integer i : inverse )
        {
            System.out.println(i);
        }
    }

If we define a couple of interfaces and utility methods:

    public static interface Mapper<FROM,TO>
    {
        public TO map(FROM arg);
    }

    public static interface Acceptor<FROM>
    {
        public void accept(FROM arg);
    }

    public static <FROM,TO> List<TO> map(Iterable<FROM> itr, Mapper<FROM,TO> mapper)
    {
        List<TO> result = new ArrayList<TO>();
        for( FROM el : itr )
        {
            result.add( mapper.map(el) ) ;
        }
        return result;
    }
    
    public static <FROM> void apply(Iterable<FROM> itr, Acceptor<FROM> apply)
    {
        for( FROM el : itr )
        {
            apply.accept(el);
        }
    }

Then we can write that code in Java5 with anonymous inner classes:

    public void sample( List<Integer numbers )
    {
        List<Integer> inverse = map( numbers,
            new Mapper<Integer,Integer>()
            {
                public Integer map(Integer i) { return -i.intValue() ; }
            }
        ) ;

        apply( inverse, 
            new Acceptor<Integer>()
            {
                public void accept(Integer i) { System.out.println(i); }
            }
        );
    }

I would argue that this syntax is significantly uglier, and less clear than the idiomatic java.

Here's what we can do with CICE:

    public void sample( List<Integer numbers )
    {
        List<Integer> inverse = map( numbers, Mapper<Integer,Integer>(Integer i) { return -i.intValue() ; }) ;
        apply( inverse, Acceptor<Integer>(Integer i) { System.out.println(i); });
    }

-- please correct me if I've done something wrong with these samples - none of the proposal authors provided a compiler to test with :)

The CICE example is a lot shorter than either of the Java5 examples (although that's partly due to my choice in code style), but I'm not sure that it's any more readable than the first version. One of the keys to clarity and readability is to make the important bits stand out, and in this example that doesn't really happen. Some of that is due to my choice in the parameter order, and the fact that the apply and map methods are static rather than members of Collection, but a large part of it is that there's a lot of characters that are mostly redundant to my understanding of the code. I don't care that the map method takes a Mapper<Integer,Integer> - I care that it is going to map the elements through the expression "-i.intValue()", and that is hidden at the end of the statement in amongst the noise of the interface and type parameters.

However, the CICE example is pretty easy to understand. I didn't have to keep consulting back to the spec to work out what I needed to write, and there was only 1 syntax to learn (and most of that was syntax I already knew)

My first attempt at a BGGA 0.2 example was:

    public void sample(List<Integer> numbers)
    {
        List<Integer> inverse = map( numbers, (Integer i) { new Integer(-i.intValue()) } ) ;
        apply( inverse, (Integer i) { System.out.println(i) });
    }

It's not a lot different from CICE. There's less noise, but more magic. I don't need to "return" keyword in the map example, and I don't need semicolons in either. However, within this choice of BGGA syntax, I don't think the removal of those syntactical elements has aided the readability in any meaningful way. In fact in both cases I originally had them in the code and then realised they were not needed.

I don't know whether the "new Integer(...)" is required. I suspect not, but I'm really not 100% sure. Without it, the closure would return "int" rather than "Integer" (the CICE example didn't have this confusion because I had specified the return type as a type parameter). However the BGGA refers to "an assignment conversion from the result type of T to the return type of U", which I can only hope includes auto-boxing. But is BGGA smart enough to know that it should handle map<?,?>( List<Integer> int(Integer) ) by setting the 2nd type parameter to Integer and auto-boxing the closure result? I hope so. The fact that I need to stop and think about it is a little worrying - there's enough compiler magic going on that I can't really call this example "straight forward"

BGGA allows an alternate syntax for this sample:

    public void sample(List<Integer> numbers)
    {
        List<Integer> inverse = map( Integer i : numbers) { -i.intValue() } 
        apply( Integer i: inverse ) { System.out.println(i) }
    }

That certainly reads a little more succinctly. It looks a bit like the Java5 foreach syntax, but not quite. It's concise and readable, but it's a little bit foreign.

I'm not sure which proposal I prefer. CICE was easy to write, and easy to understand, but I'm not sure it adds enough syntactical benefit to actually make the language significantly better. If we end up with CICE closures, I suspect a lot of people will keep writing code in the style of the first example. That's OK - the first example is perfectly readable - but it might be a sign that CICE doesn't give quite enough syntactical sugar. I do think CICE will provide some readability benefits for list searching/filtering though.

        List<Integer> positive = select( numbers, Predicate<Integer>(Integer i) { return i >= 0 ; }) ;

is (IMO) more readable than:

        List<Integer> positive = new ArrayList<Integer>( numbers.size() );
        for( Integer i : numbers )
        {
            if(i >= 0 ) 
            {
                positive.add( - i.intValue() ) ;
            }
        }

But the BGGA:

    List<Integer> positive = select( Integer i : numbers) { i >= 0  } 

is significantly easier to read. It's clear what the code is trying to do - it's less clear (particularly to less experienced developers) how it accomplishes it.

Ultimately, I see this as an intractable problem. The goal here is to add a concise, neat and elegant syntax for closures to a language which is none of those things. Any closure proposal that meets that goal is going to look out of place in the overly-verbose, staticly-typed world of java. I want closures, I think they're an important part of any modern programming language, but there's a big risk of this turning into a case of lipstick on a pig.

BGGA ends up providing a syntax that is quite similar to the syntax provided by some other languages. The syntax really helps in writing concise, intentional code, but it doesn't really have a "java feel" to it.

Java isn't ruby. Even if we wanted to turn it into ruby, it's too late. So java needs a closure syntax that looks and feels like java. I think BGGA misses the mark on that one. But if we're going to add a closure syntax it at least needs to offer some advantage over what we currently have, and I think CICE falls down there.

Turning to some of the semantic concepts involved, I really like that fact that CICE treats everything as an implementation of a SAM. There's no new types, no new methods on Class/Object, not much new to learn. It also forces library writers to develop against interfaces rather than function types. This has 2 specific advantages that I can think of

  1. Teams who reject the new syntax will not be prevented from using those new APIs.
  2. It opens up some interesting possibilities to use dynamic proxies

But in the end I can't really support CICE for the use cases I've played with here. It simply doesn't improve the clarity of the code sufficiently to warrant a change to the language - even such a simple change. Perhaps when I dig into more complex uses cases its value will show through, but for simple cases, I can't see it.

Neither proposal has yet included any discussion of APIs (or new syntax) for manipulating closures. I haven't seen a nice way to perform currying in either proposal (perhaps I'm just not imaginative enough), and neither proposal seems to allow taking a reference to an existing method (either static or non-static). In my "apply" example above, I see no real reason why I had to write a new closure for System.out.println(i), that's already a void(Integer) method, why can it not be assigned to a function type? In BGGA that syntax is simple enough that the loss is quite small. In CICE that ability is missed.

I didn't need any of the complex BGGA features. No synchronized parameters. No non-local returns. No "Unreachable" types. I still question whether those features are worth adding to the language. There's a lot of complexity there for a fairly uncommon use case.

Partly it's an issue of balance: One of my other concerns with CICE is that it follows the same route the anonymous inner classes took us down the first time - add minimal changes to the language in order to cater for a particular set of use cases. I'm not sure that's what we need. We don't just need to be able to do the same things better, we need to be able to do better things. We all decided quite a long time ago that anonymous inner classes aren't enough to provide the expressiveness developer are after. What happens when we decide that CICE isn't enough either? Do we keep adding little bits of syntax until we get where we want to go? I think BGGA is going the other direction. It's adding a lot of stuff that we haven't tried before, and I don't think we (or they) truly understand the consequences. Do we really need all of that functionality now? Can we be confident that the decisions we make in our current relative ignorance will turn out to be the right ones? Perhaps it is possible to implement part of BGGA in Java 7 and then refine it after that. I'm not really sure how to approach it, but it seems like a lot to through into the language without a good feel for how it will play out.

I'll be very disappointed if Java 7 ends up having either CICE (as it currently stands) or BGGA (any version <= 0.2) because I don't think either of the proposals manages to get the balance of "java-ness", readability, expressiveness, and clarity that we need.

Side Note: I wrote all the samples in vi, and was pleasantly surprised to find I could still write java code without an IDE. I had expected to be cursing at the unnecessary verbosity of java, but it was quite manageable for the small snippets of code I was writing