Saturday, August 19, 2006

What's the point of Closures?

A number of people have asked me: What's the point of closures? Can't you accomplish pretty much the same thing with the existing language constructs? What does it really buy you?

If you haven't programmed using closures, and you've gotten used to the Java idioms for the past ten years, it might be hard to see what closures really buy you. This is my attempt to give you a glimpse of that, by way of an extended example.

The problem

Suppose you are working with an application that maintains a list of documents, and for each individual in some set a list of document annotations. For the sake of this example, suppose the two lists are parallel. That is, if you take the list of annotations from an individual, the values correspond elementwise with the elements of the document list. To make this more concrete:

class Document { ... }
class DocAnnotation { ... }
class Person { ... }
class Documents {
    static List<Document> allDocuments();
}
class Persons {
    static Set<Person> allPersons();
    static Person GEORGE_W_BUSH = ...;
}
class DocAnnotations {
    static Map<Person,List<DocAnnotation>> allAnnotations = ...;
}

Now, you might ask a question such as: Has George Bush annotated any documents mentioning Iraq as secret. In this hypothetical application, you might code that up something like this:

boolean bushMarkedAnyIraqDocsSecret() {
    Iterator<Document> docI = Documents.allDocuments().iterator();
    Iterator<DocAnnotation> annI =
        DocAnnotations.allAnnotations.get(GEORGE_W_BUSH).iterator();
    while (docI.hasNext() && annI.hasNext()) {
        Document doc = docI.next();
        DocAnnotation docAnn = annI.next();
        if (doc.mentions("Iraq") && docAnn.marked("secret")) {
            return true;
        }
    }
    return false;
}

We could abstract this over what we're looking for in the document, who'se annotations we're looking for, and what kind of annotation we're looking for:

boolean personAnnotatedOnKeyword(Person person, String ann, String key) {
    Iterator<Document> docI = Documents.allDocuments().iterator();
    Iterator<DocAnnotation> annI =
        DocAnnotations.allAnnotations.get(person).iterator();
    while (docI.hasNext() && annI.hasNext()) {
        Document doc = docI.next();
        DocAnnotation docAnn = annI.next();
        if (doc.mentions(key) && docAnn.marked(ann)) {
            return true;
        }
    }
    return false;
}

It is possible that abstracting in this way allowes us to avoid repeating this loop throughout the code, if the code frequently needs to ask this kind of question. Abstracting common code is good because, among other things, it allows us to reduce the number of things we need to change when we refactor code. For example, if we were to change the representation of a person's annotations to be a Map<Document,DocAnnotation> instead of List<DocAnnotation>, or make a DocAnnotation contain a reference to the Document, we would have to change this kind of loop everywhere it appears. So having a single place where the loop is written is a good thing, as there are fewer places in the code that depend on the exact representation of the data.

Abstracting the loop in JDK5

The next step is to try to abstract the loop itself. Java provides some convenient looping constructs, including the recently introduced for-each loop with its Iterable interface. We can use that, but we need to introduce a type over which we're iterating:

class DocAndAnnotation {
    final Document doc;
    final DocAnnotation docAnn;
    DocAndAnnotation(Document doc, DocAnnotation docAnn) {
        this.doc = doc;
        this.docAnn = docAnn;
    }
}

Now we can provide looping support by writing the loop only once in the code like this

Collection<DocAndAnnotation> docsWithAnnotations(Person person) {
    Iterator<Document> docI = Documents.allDocuments().iterator();
    Iterator<DocAnnotation> annI =
        DocAnnotations.allAnnotations.get(person).iterator();
    List<DocAndAnnotation> result =
        new ArrayList<DocAndAnnotation>();
    while (docI.hasNext() && annI.hasNext()) {
        Document doc = docI.next();
        DocAnnotation docAnn = annI.next();
        result.add(new DocAndAnnotation(doc, docAnn));
    }
    return result;
}

This allows us to write the original loop like this:

boolean personAnnotatedOnKeyword(Person person, String ann, String key) {
    for (DocAndAnnotation docAndAnn : docsWithAnnotations(person)) {
        if (docWithAnn.doc.mentions(key) && docWithAnn.docAnn.marked(ann)) {
            return true;
        }
    }
    return false;
}

So far so good, but this solution has an unfortunate feature: it constructs the entire list even if the answer can be found by looking at only the first annotated document. We can do slightly better by constructing a lazy iterator instead of an eager list. We do that by rewriting docsWithAnnotations as follows:

Iterable<DocAndAnnotation> docsWithAnnotations(Person person) {
    final Iterator<Document> docI =
        Documents.allDocuments().iterator();
    final Iterator<DocAnnotation> annI =
        DocAnnotations.allAnnotations.get(person).iterator();
    return new Iterable<DocAndAnnotation>() {
        public Iterator<DocAndAnnotation> iterator() {
            return new Iterator<DocAndAnnotation>() {
                public boolean hasNext() {
                    return docI.hasNext() && annI.hasNext();
                }
                public DocAndAnnotation next() {
                    return new DocAndAnnotation(docI.next(), annI.next());
                }
                public void remove() {
                    throw new UnsupportedOperationException();
                }
            };
        }
    };
}

Now, without changing personAnnotatedOnKeyword, the same loop works without the overhead of building the entire List<DocAndAnnotation>.

This program does, however, produce a large number of small, transient garbage objects. The Iterator, Iterable, and DocAndAnnotation objects are all short-lived and simply exist to convey data from one part of the program to another. This is not necessarily a problem; HotSpot has a number of garbage-collection algorithms that are good at allocating and reclaiming short-lived objects. But in some applications it could contribute toward a performance bottleneck.

Can the looping code be refactored to avoid all these small allocations? The answer is yes, and there is a standard idiom for doing that in Java. The idea is to turn the control structure of the loop inside-out. Rather than having the personAnnotatedOnKeyword perform the iteration, we have a library method perform the iteration and pass the values to a snippet of code provided by personAnnotatedOnKeyword. That would look something like this:

interface WithDocumentAndAnnotation {
    void doIt(Document doc, DocAnnotation docAnn);
}
void docsWithAnnotations(
        Person person, WithDocumentAndAnnotation body) {
    Iterator<Document> docI = Documents.allDocuments().iterator();
    Iterator<DocAnnotation> annI =
        DocAnnotations.allAnnotations.get(person).iterator();
    while (docI.hasNext() && annI.hasNext()) {
        Document doc = docI.next();
        DocAnnotation docAnn = annI.next();
        body.doIt(doc, docAnn);
    }
}

A client can now iterate through a person's annotations by providing a snippet of code in the form of a class that implements the interface:

boolean personAnnotatedOnKeyword(
        Person person, final String ann, final String key) {
    class MyBody implements WithDocumentAndAnnotation {
        boolean result = false;
        public void doIt(Document doc, DocAnnotation docAnn) {
            if (doc.mentions(key) && docAnn.marked(ann)) {
                result = true;
            }
        }
    }
    MyBody body = new MyBody();
    docsWithAnnotations(person, body);
    return body.result;
}

This solves the transient memory allocation problem (if it even was a problem), but this version of the program again unnnecessarily iterates through all of the documents even if it needs to iterate through only a few to compute its result. We can fix that by modifying the WithDocumentAndAnnotation interface's method to return a boolean, which indicates whether or not iteration should continue or whether the loop should abort. This may enable many of the old clients of the docsWithAnnotations method to migrate to the new API, but it may not satisfy the needs of all of them. Presumably we could modify the interface further as we discovered different patterns of control-flow used by clients that iterate through documents and their annotations. We leave the details as an exercise to the reader.

Abstracting the loop with Closures

Closures provide a somewhat more convenient way to abstract the loop:

void docsWithAnnotations(Person person, void(Document,DocAnnotation) block) {
    Iterator<Document> docI = Documents.allDocuments().iterator();
    Iterator<DocAnnotation> annI =
        DocAnnotations.allAnnotations.get(person).iterator();
    while (docI.hasNext() && annI.hasNext()) {
        Document doc = docI.next();
        DocAnnotation docAnn = annI.next();
        block(doc, docAnn);
    }
}

This looks almost the same as our last version using JDK5, except that it does not require the introduction of the WithDocumentAndAnnotation interface. Let's see what the client looks like:


boolean personAnnotatedOnKeyword(
        Person person, final String ann, final String key) {
    docsWithAnnotations(person, (Document doc, DocAnnotation docAnn) {
        if (doc.mentions(key) && docAnn.marked(ann)) {
            return personAnnotatedOnKeyword: true;
        }
    });
    return false;
}

That's it. If we adopt the modifications to the proposal suggested in the Further Ideas section, the client would look something like this:

boolean personAnnotatedOnKeyword(
        Person person, final String ann, final String key) {
    docsWithAnnotations(person) (Document doc, DocAnnotation docAnn) {
        if (doc.mentions(key) && docAnn.marked(ann)) {
            return true;
        }
    }
    return false;
}

The only transient objects created in this version are the closure object itself and the two iterators used in the implementation of docsWithAnnotations. As you can see, the caller of docsWithAnnotations can use control-flow operations like return without the implementation of docsWithAnnotations having to anticipate what kinds of control-flow will be required.

Now, in the interest of full disclosure I should mention that the return statement within the closure is likely to be implemented under the covers using exceptions. That's one more transient object we should count. As for the performance of using an exception in this way, I'm told by HotSpot engineers that an exception used this way is largely optimized away by the VM if found in performance-critical code. The most expensive part of exception handling by far is capturing the stack trace when creating the exception, and we would want to create exceptions for this purpose without stack traces.

That really is it. All of the design iterations we went through to handle variations on this problem in JDK5 simply don't arise as issues. That's the beauty of closures: they allow you to easily abstract away aspects of code that would otherwise require complex contortions.

A slight update on my current feelings about the draft spec. I think we are likely to drop the special syntax for a nonlocal return, and have a different syntax for returning from a closure. This is hinted at in the Further Ideas section. "return" would mean return from the enclosing method or function, and if you're inside a closure you would write a statement something like "^ expression;" to return a value from the closure. Most value-returning closures are unlikely to need this syntax, since they can often be expressed using the "(args) : expression" form.

29 comments:

Reinier Zwitserloot said...

I still don't see the point.

To wit: You claim that the creation of all those small objects might just be overhead, then immediatly go on the defense and say they generally don't. Which is it?

I'll tell you: They are NOT OVERHEAD. Recent versions of the garbage collector are more efficient in the allocation and deallocation of short-lived objects than even finely tuned C code because entire blocks of short-lived object memory space gets dealloced all in one fell swoop.

Let me repeat this just so its crystal clear: Object creation overhead ONLY OCCURS IF THE OBJECT LIVES LONG. In these examples, long doesn't qualify. After a single iteration, the DocAndAnnotation object can be gced, which is definitely well into 'short lifespan' territory.

Overhead: Zero. Nothing. Nada. In 1.6 the entire thing will probably end up being shoved on the stack and destructed as part of the act of returning from that 'doIt' method code.

So, now that that sneaky attempt to chalk a benefit on the board for closures has been dealt with, let's get to the REAL meat and potatoes.

But here, again, there's no benefit.

I see 2 things you got:

1. The way you can avoid having to declare a new 'DocAndAnnotationChecker' kind of interface - the thing with the doIt method.

I freely grant that the current syntax for writing a quick off the cuff implementation of a simple interface is needlessly expansive. For example, to sort a list with your own version of order, you can provide an implementation of the Comparator interface, and to provide it, you'd have to make something like:

new Comparator() {public int compare(Integer a, Integer b) {return a-b;}}

Oy vey, that's a lot of code that adds little to nothing. That needs to be fixed. How acceptable would this be:

new Comparator(Integer a, Integer b) {return a-b;}

I'll take that. A closure would look something like:

(Integer a, Integer b) {return a-b;}

which is hardly simpler, and there you just lost very significant information: The contract under which the closure operates (or: The relevant namespace and type), and what it is for.

Here's a little known fact: An anonymous class in java can't have constructor parameters. new (interfacename) (parameters) {codeblock} is completely unambiguous: It's illegal syntax in all versions of java up to now. Furthermore, if something gets used enough, it tends to sneak into the language. Exhibit A: The foreach syntax.

All that needs to happen is a lobby for simpler syntax when creating anonymous instances of single-method interfaces.

That takes care of easier, less convoluted syntax.

Leaves the flexibility of a real closure to hop out anywhere. Your 'return outermethod: true' statement.

Yup, anonymous classes can't pull that off. But do you want them to? It's spaghetti goto all over again in some circumstances.

Let's say I'm wrong. I'm an old fart, I am willing to submit I'm being needlessly old fashioned here. The implementation, as you said, has something to do with exceptions.

Let's say everyone and their uncle actually finds serious use for escaping these things and starts to use specially made exceptions to do the job. Whole 'pattern' books get filled writing about the little trick.

Some java version down the line will introduce easier syntax for it, possibly even exactly what you just mentioned. It will all get compiled to exactly the same bytecode as before, it's just a compiler-time implemented shortcut.

That's good. That's the way it should be: The anti perl soup approach: Introduce easier syntax ONLY if people actually are going to use it.

Now, just to make this clear: I'm not at all a java purist. I loved every single last addition to java5 syntax and I'm clamoring for many more. There are also things that cant be solved now with convoluted syntax. Something like a generator (look up the 'yield' keyword for python, or search for 'duff's device' which is how you can write coroutines and generators for C) is just not that simple to implement, no matter how much boilerplate syntax you're willing to tolerate.

An experiment with introducing something like yield in java, that would be very very interesting.

There's also a shot at doing something like that with libraries. Most of java's actual threading capabilities are done through libraries (check the ThreadLocal, the Semaphore, etcetera. 'synchronized' is more a low level thing you shouldn't use anymore).

How about doing generators that way? You'd be looking at a device I call 'cothreads' - they have all the separate stack trace characteristics of threads, but they do not actually run as a separate thread on the processor. A whole bunch of cothreads exist in one thread, and the only way one of those cothreads ever gets a slice is when some code calls on it explicitly to run - and then it won't return until it explicitly returns.

Thinking of clever little hacks like that actually serves to keep the language simpler. Easier to learn. Yes, easier to read.

And above all else: Easier to read for your favourite IDE (Eclipse, NetBeans) internal parser engine. A second set of eyes that underlines in red any problems as soon as your fingers commit the error on the keyboard.

Python doesn't have that. Python won't.

That's cool. Python is good for writing certain types of code faster, just as maintainable as a java version. That's python's raison d'etre. If java emulated all of python's code ideosynchracies...

you'd have a really bad python. There's no need. Python is a much better Python.

Java has its own way of looking at programming. Closures do not 'fit', at least not the way they are being suggested now. All java objects have an actual explicitly declared type - even anonymous classes. You can use reflection to look at that, you can get eclipse to show relevant javadocs by simply mousing over a call.

In closures, all that is no longer possible.

Anonymous said...

Interesting reading!

One benefit of closures I think you omitted (apologies if I missed it), which is probably more important than performance aspects (and it's not certain that closures even could help with performance at all), is that of clean up of the iterated resource. This is especially useful with database access patterns: closing of the connection, statement(s), result set(s), all of these can be done quite neatly with closures in languages like Ruby (and there a few code examples, from tutorials from writers like Dave Thomas). In Java you can do this (clumsily) using callbacks (or resort to frameworks like Spring)... but real closures would solve this far more elegantly.

Also, closures used this way can simplify code, for example with things like XML parsing. Currently it's either "parser in control" (SAX) or "app in control" (StAX), leading to one side or the other has to 'manually' keep track of what's going on, leading to quite inelegant code.

Anonymous said...

I strongly agree with reiner zwitserloot - the (proposed) ugly syntax for closures is a heavy price to pay for the relatively small gain over using anon inner classes. Cleaning up the syntax for creating anon inner classes would be a bigger win.

One of the joys of using Java when it first came out was how easy the syntax and libraries were to use. It got a little harder with Generics (easy to call but hellish to implement generified code); but the proposed syntax for closures in Java is likely to create a real big and ugly obstacle for those new to the language. I'm not sure why it needs to be so 'weird' compared to python or even javascript.

Anonymous said...

Hi,

To repeat something i mentioned on Peter's blog, but maybe you are the right person to have asked first...

[snip]

...if we're allowing lambda-calc-like things, can we please also support Curried functions, ie partially evaluated with one or more of the arguments to a multi-arg function.

Just think what HotSpot could do in generating the specialised version of a function! Even in Standard ML days 20 years ago I found it a useful optimisation.

(For the record, what I call a Curried function is a specialised partial evaulation of say a new function "twice" = "f 2" where f is "x * y", ie takes two args.)

Occasionally I simulate this in C++ or Java, but to have direct support for it in the language and the JIT/runtime would be fab. I do occasionally have dreams about it. Yes, sorry, I do!

Rgds

Damon

Anonymous said...

The reason I like Java is because it limits the ways in which newbies can screw me and lose money for my employer. This is a perfect example of a feature that will add no real value because it doesn't let us do anything (in business terms) we weren't able to do before, it doesn't save us development costs and it will cost us dearly in maintenance costs.

Soon Java will be open source, please just add this feature to your personal branch and don't screw me over with it. We have a limited amount of money we get, and cancer research, as an example, would be a better way to use money than amusing programmers.

Ricky Clarkson said...

Reiner said this:

"Here's a little known fact: An anonymous class in java can't have constructor parameters. new (interfacename) (parameters) {codeblock} is completely unambiguous: It's illegal syntax in all versions of java up to now."

However, he's wrong.

class X
{
X(int x)
{
new X(5){};
}
}

This is highly dodgy code, but it does compile. I have no idea whether it has always compiled.

Personally I don't even use named constructors (anonymous classes only), so it doesn't interest me.

I think Neal, with the performance part, was merely trying to predict the complaint and address it, he wasn't saying there will be overhead.

Depending on the syntax chosen, then yes, a simpler syntax for anonymous classes might be enough. This is possible, but not very likely:

Collections.sort(numbers,{a-b});

There are various steps towards the anonymous class syntax that you can take as you disambiguate, e.g., putting a return statement in there, declaring a and b, etc., and ultimately for some/many cases you might end up with roughly the anonymous class syntax.

The points about Python are easily rebutted by referring to Haskell, which has closures, stronger typing than Java, and a specification.

Anonymous said...

OMG! What a horribly complex example for a concept that seems so simple on other languages. What I really want to know is:
* is it going to be similar to Ruby's yield?

Can I do something like:

Collection c;
String songName;
c.find { |Song aSong| return songName.equals(aSong.getName; }

and

c.each { |Song tempSong|
System.out.println(tempSong.getName();
}

Ricky Clarkson said...

I already do have a c.find equivalent in Java, and use it.

public static <T> boolean any(ViewIterable<T> iterable,Transform<,Boolean> transformer)
{
for (final T item: iterable(iterable))
if (transformer.transform(item))
return true;

return false;
}

So you could use this as:

Collection<Song> c;
String songName;
System.out.println(any(c,new Transform<Song,Boolean>()
{
public Boolean transform(Song aSong)
{
return songName.equals(aSong.getName());
}
});

This looks awful, and would be much simpler to read as:

System.out.println(any(c,{songName.equals(getName());}));

or almost any other closure-like syntax than anonymous classes.

I'm expecting this to look terrible on the blog, so I've also posted it to my website: http://cime.net/~ricky/tmp/closure.txt

david said...

IMO we should merely make some changes to the Collection API, something like this:

interface Callback {
void callback(Object element);
}

Collection.call(Callback callback);

In that call() method, we loop over all elements of the collection, with each iteration calling Callback's callback() method, thereby passing the element.

void callback(Callback callback) {
for (Object element; elements();) {
callback.callback(element);
}
}

We can then use this as follows:

List aList = new ArrayList();
aList.callback(new Callback() {
public void callback(Object element) {
System.out.println(element.toString());
}
});

Anonymous said...

Check out my examples on JavaLobby where this argument is raging:

Ray Cromwell's closure examples

-Ray

p.s. callback interfaces are terrible, the version you posted is not generified, so would require casts for any non-trivial collection, and is just plain verbose.


Here's how I would print out a List.

list.each (Object o) (System.out.println(o.toString()); }

pulihora said...

I have some stupid questions:
C has pointer to functions : once we define a pointer to a function, we can assign real functions to it,
pass it it as an argument to another functions, etc.

Is closure similar to that.

Anonymous said...

"One of the joys of using Java when it first came out was how easy the syntax and libraries were to use. It got a little harder with Generics (easy to call but hellish to implement generified code); but the proposed syntax for closures in Java is likely to create a real big and ugly obstacle for those new to the language. I'm not sure why it needs to be so 'weird' compared to python or even javascript."

+1000


"IMO we should merely make some changes to the Collection API, something like this:

interface Callback {
void callback(Object element);
}

Collection.call(Callback callback);

In that call() method, we loop over all elements of the collection, with each iteration calling Callback's callback() method, thereby passing the element.

void callback(Callback callback) {
for (Object element; elements();) {
callback.callback(element);
}
}

We can then use this as follows:

List aList = new ArrayList();
aList.callback(new Callback() {
public void callback(Object element) {
System.out.println(element.toString());
}
});"

+500

Neal Gafter said...

Sorry, folks, you can't add methods to existing interfaces, because any existing implementations of the interface would no longer compile. Backward compatibility is important!

Tom Palmer said...

Reinier, why wouldn't mouseover in an IDE work to see the type of a closure expression? There's no identifier, but there's still some space that belongs to the construct and not to other identifiers. One could get accustomed

In general, closures are the right way to do things, and current block constructs in Java are just hard-coded hacks.

Now, I do have some misgivings (for instance with the new function types when single-method interfaces by themselves are sufficient), and maybe I'll blog about those, but if they really add closures to Java, I don't think I'll be complaining.

Tom Palmer said...

Pulihora, Java objects are already like C function pointers in how they are used. You just can't reference a method directly as an object. Closures don't necessarily add this feature, either. I think it's okay not to mix these two features. In C (at least in some versions), you can declare a function within another function, but you can't always safely access local variables. Closures allow this.

Anonymous said...

Could anyone show a simple example showing the point of Closures?

EricR said...

Yes, closures are very useful, but can we improve the readability of the proposed syntax?

"Thou shalt not add reserved words to the language" is an honorable goal, but it has it's costs.

amorfis said...

Access to non-final variables is great, but code readability suffers. I really prefer to create interface and anonymous class. It has worse performance? Well, hardware is cheap today, programmer's time is not, so I prefer readable code than fast one. But this access to non-final variables... can't we do something to have it with old-style anonymous classes? I would prefer it much more.

Tom Palmer said...

Here's a simple example of closures (but with extra explanatory text). It doesn't use the same syntax as in the recent semi-official proposal. It's something I baked up on my own a while back:

http://bagotricks.com/blog/2006/06/19/java-5-for-loops-bad-for-streaming/

Anonymous said...

yo, I'm a Swing develper, Everytime when i wanted to add some listener um.. keyboard, mousemove ...etc.
Im tried to do some hack on the anonymous class syntax...
Why should I wrapper up my functions using a Listener, Adaptor ??
I really dun want to type these boilerplate again and agin..
addxxxxxx(new xxxxListener() {
public void onMouseMove(.....) {
myOwnOneMouseMoveFunction(....);
}
});

I read some kool examples about closeure on Ruby and even smalltalk, they are exactly what I want !!

Looks at a example about closeure:

allCustomerList.find((Customer c): c.age >30);

or

allCustomerList.find(myFunctionOnSelectingRules());

isn't is much simpler than

allCustomerList.find( new Closure() {
public List findCustomerThatAgeAbout(int age) {
......
}
});

All of forks said anonymous is too verbose in Javalobby b4. And now u forks said anonymous class is just more clear and readable....
OMG, are u spy from yet another java language.

Isn't is the power of ruby that u forks are looking for.??
Isn't this is one of the reason that someone said Ruby is beyond Java ??

I remembered that before the proposal, a lot of forks request for closeure in Sun's Java Bug DB, Javalobby,....etc
And someone even said that it is a shame that Java has no real closure support, but has the anonymous class hack.

Now the time is come, why not take it???

If u guys dun understand how power it is, take a look here about closure in C#.
http://spellcoder.com/blogs/bashmohandes/archive/2006/06/12/143.aspx
http://pocketxp.spaces.live.com/blog/cns!75810CFE740B6130!220.entry

IMO, I can read and understand all the example easily, it is just as same as the closure in smalltalk.

If u just treat, it is a way to remove the stupid anonymous class hack, u will find that it is god damn useful.

Just my 2cents,
void(int,int,int,int) function = xxxxx();
it may be too verbose sometime, time to add type inference.?
http://en.wikipedia.org/wiki/Type_inference
"This feature is planned for Fortress, C# 3.0 and C++0x"

PS: Mr Neal: PLZ ADD IT and SAVE ME FROM THE XXXXADAPTOR TYEPING HELL

Anonymous said...

@amorfis:
I wouldn't regard it as a good idea to have access to non-final local vars from local (anonymous) classes.
Local classes have to be instantiated to call their method(s) and this reference might escape from the current method frame at any point (which is e.g. done all the time with Listeners in Swing).
Therefore a private copy of each local final var is stored inside the anonymous classes' instance (and this copy is really accessed by the code in the local classes method(s)!) - if the local var is changed before and/or after the escape of the reference, which value of the local var should be considered the "right" one to use in the local classes' method(s)?
Forcing local variables to be final in order to access them in local classes was the simplest solution to avoid possibly very subtle bugs in such situations.

and to mr. "yo, i'm a swing developer" (I really don't get what you mean with "forks" - "folks" perhaps?):
The whole point of listeners is that they're defined as interfaces.
granted, it is a little more typing effort (you're not using a good IDE, are you?), but what do closures buy you for Listeners that have more than one callback method?
A simplified notation of local (anonymous) classes would suffice - closures only make sense if Java would adopt some other language features relying on them. Right now, they'd be just syntactic sugar...

Anonymous said...

@Anonymous Swing developer:
For the boiler plate swing code issue, I code on a tiny open source framework (whenever I got some time to kill) that allows me to write stuff like:

package net.java.tangogui.test;

import javax.swing.JButton;
import javax.swing.JFrame;

import net.java.tangogui.backend.EventManager;
import net.java.tangogui.events.Bind;

public class Simple1 extends JFrame {
JButton button;
public Simple1() {
button = new JButton("Click me!");
this.add(button);
(new EventManager(this)).addEventFace(this); // causes event binding
}

@Bind("button.onClick") // the magic of annotations at work here...
void buttonClicked(){
System.out.println("the button was clicked!");
}

public static void main(String[] args) {
(new Simple1()).setVisible(true);
}
}

With the correct classpath, this (very!) simple example runs and works.

swamptrog said...

yesss, I want to agree with the fellow who suggested Collection just (and others) just need to have callbacks so you don't need a looping construct at all for most cases.

I also really like the idea of simpler syntax for implementing anonymous inner classes.

Most of the time, anonymous inner classes implement an interface with a single method, or overide a single method of an abstract class.

Here's a simplified syntax where you just write the method parameters and body, isntead of the full anonymous class declaration.

a.doComparison(compare(Object o1, Object 02){
//yada yada
});

Tell me why the compiler can't figure out the doComparison takes a Comparator, then automatically compile a Comparitor, substituting the method body. This would be a nice shortcut for the common case.

to generalize, why can't the compiler do the same thing when more than one method needs to be implemented:

a.doCompareAndContrast(

compare(Object o1, Object 02){
//yada yada
}

contrast(Object o1, Object 02){
//yada yada
}
);

Anonymous said...

yesss, I want to agree with the fellow who suggested Collection just (and others) just need to have callbacks so you don't need a looping construct at all for most cases.

I also really like the idea of simpler syntax for implementing anonymous inner classes.

Most of the time, anonymous inner classes implement an interface with a single method, or overide a single method of an abstract class.

Here's a simplified syntax where you just write the method parameters and body, isntead of the full anonymous class declaration.

a.doComparison(compare(Object o1, Object 02){
//yada yada
});

Tell me why the compiler can't figure out the doComparison takes a Comparator, then automatically compile a Comparitor, substituting the method body. This would be a nice shortcut for the common case.

to generalize, why can't the compiler do the same thing when more than one method needs to be implemented:

a.doCompareAndContrast(

compare(Object o1, Object 02){
//yada yada
}

contrast(Object o1, Object 02){
//yada yada
}
);

Howard Lovatt said...

Your examples are far from convincing, I would code the example using inner classes as:

abstract class WithDocumentAndAnnotation {
boolean hasNext = true;
abstract void doIt( Document doc, DocAnnotation docAnn );
}

boolean docsWithAnnotations( final Person person, final WithDocumentAndAnnotation body ) {
final Iterator<Document> docI = Documents.allDocuments().iterator();
final Iterator<DocAnnotation> annI = DocAnnotations.allAnnotations.get( person ).iterator();
while ( body.hasNext && docI.hasNext() && annI.hasNext() ) body.doIt( docI.next(), annI.next() );
return !body.hasNext;
}

boolean personAnnotatedOnKeyword( final Person person, final String ann, final String key ) {
return docsWithAnnotations( person, new WithDocumentAndAnnotation() {
public void doIt( final Document doc, final DocAnnotation docAnn ) {
if ( doc.mentions( key ) && docAnn.marked( ann ) ) hasNext = false;
}
} );
}

Which I think is much simpler than using closures. Look how great the inner class is, it carries both the field and the method in one object. You have to jump through hoops with closures. If you shorten syntax, e.g.:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6389769

Then the example would be:

abstract class WithDocumentAndAnnotation {
var hasNext = true;
abstract void doIt( Document doc, DocAnnotation docAnn );
}

boolean docsWithAnnotations( final Person person, final WithDocumentAndAnnotation body ) {
final docI = Documents.allDocuments().iterator();
final annI = DocAnnotations.allAnnotations.get( person ).iterator();
while ( body.hasNext && docI.hasNext() && annI.hasNext() ) body.doIt( docI.next(), annI.next() );
return !body.hasNext;
}

boolean personAnnotatedOnKeyword( final Person person, final String ann, final String key )
return docsWithAnnotations( person, WithDocumentAndAnnotation() ( final doc, final docAnn )
if ( doc.mentions( key ) && docAnn.marked( ann ) ) hasNext = false;
);

Which is shorter than closures and without another concept.

In short, closures are a poor man's inner class.

Infernoz said...

Javascript can do closures because it has proper referenceable functions (methods is disguise). It's so easy, why can't Java use this same trick of supporting functions via class method and object method references? I think Java should also support anonymous methods, for on-the-fly function uses. If Java used this approach, closures would be a doddle, easy to read and probably remove the need for the final variable hassle, with inner classes. There could even be an adapter mechanism for methods requiring interfaces.
I think closures is only a major issue because java.lang.reflect was botched and was made more expensive than it needed to be.

Anonymous said...

Neil Gafter says:
Sorry, folks, you can't add methods to existing interfaces, because any existing implementations of the interface would no longer compile. Backward compatibility is important!

Well, we can't do that - but SUN obviously can and has done that - for example in the various versions java.sql.Connection and java.sql.ResultSet - which made upgrading to a new JDK a hard time for us!

Why didn't they use the simple solution of providing extended Interfaces that inherit from the older ones?

Horst M.

Anonymous said...

I for one still fail to see the "point of Closures". I was perfectly happy with your final pre-JDK5 solution :).

For me it looks as yet another sad step into java obfuscation. Is there really no other way to evolve a programming language?

blackheartsaur said...

> An anonymous class in java
> can't have constructor parameters
One workaround for this is to use 'factory method'. Like this:

AICSuperclass anonInnerClass = new AICSuperclass() {
public AICSuperclass myVerySpecialMethod(String constructorParam) {
return this;
}
}.myVerySpecialMethod("My Constr Param");