A closure is an anonymous function (aka lambda expression) in which all free variables can be accessed (even if they are not final). Furthermore, in the tradition of Smalltalk, the closure should be able to return directly from the method enclosing the closure definition (aka non-local return).
In the Java™ programming language, closures can be simulated to some extent with anonymous classes but these cannot access non-final local variables and have no way to exit the method containing the definition besides throwing an exception (which should not be used for control flow).
Closures have been a favorite of most Smalltalk freaks and has gotten renewed interest in languages such as Ruby.
Anonymous classes, although useful, can be a tad verbose and tiresome to type so this proposal must address the proper closure of free variables and non-local return as well as suggest a consice syntax.
"Referencing Names from the Enclosing Scope" fails to define how non-final locals will be handled. Is there an UnmatchedEnclosingVariableAccess if the closure escapes its scope? Or will non-final locals be boxed?
I have a feeling that especially non-local control transfer should not be regarded as a must. I think people are pretty much used to the semantics of inner classes, they just hate the syntatic impact.
In doubt, a solution that is closer to "concise anonymous inner classes" than to "closures like in smalltalk" would still be immensely useful, even if they do not match the expectations of those who have seen the holy land. I'd definetely prefer it to "Closed, not feasible".
MatthiasPosted by Matthias Ernst on August 18, 2006 at 06:02 AM PDT #
Posted by Andy DePue on August 18, 2006 at 08:47 AM PDT #
Posted by Dmitri Trembovetski on August 18, 2006 at 10:29 AM PDT #
Posted by Eugene Vigdorchik on August 18, 2006 at 12:21 PM PDT #
Posted by Michael Nascimento Santos on August 18, 2006 at 02:04 PM PDT #
Are or can functions/closures (be made) Serializable?I doubt it. Webservice and the like are probably a better solution than serializable closures.
In practice, will functions/closures classes extend a specific supertype, such as Function?Most likely.
Posted by Peter von der Ahe on August 18, 2006 at 02:31 PM PDT #
Posted by Peter von der Ahe on August 18, 2006 at 02:34 PM PDT #
Posted by Rodrigo Kumpera on August 18, 2006 at 02:50 PM PDT #
I should read the proposal in detail of course, but 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
Posted by Damon Hart-Davis on August 18, 2006 at 04:23 PM PDT #
Posted by Peter von der Ahe on August 18, 2006 at 05:12 PM PDT #
Posted by Tom on August 18, 2006 at 08:15 PM PDT #
boolean hasOranges =
list.detect(
boolean ( Object item ) {
return item.equals( "orange" );
} );
Posted by Robert DiFalco on August 19, 2006 at 08:22 AM PDT #
// # used here to help the compiler. Method m = myObject#myCall (Object, String);Then:
public void iterateOver (Method m, List myitems)
{
for (Item item : myitems)
{
// It would be nice to use . here but
// # would also be possible to help the
// compiler...
// Would also be useful to have a
// "callMethod" method that allows direct
// access rather than passing an array
// of args.
m.myCall (item, 'hello world');
}
}
It would also be nice to reference methods in a Class directly as well. For example:
public void doSomething (Class c)
{
c#eval ('hello world');
}
Posted by marcusk on August 19, 2006 at 05:58 PM PDT #
Method m = myObject#myCall (String);And item would be the object to call the method on.
Posted by marcusk on August 19, 2006 at 08:01 PM PDT #
Posted by Karsten Wagner on August 21, 2006 at 06:31 AM PDT #
Posted by Marcus Breese on August 21, 2006 at 11:12 AM PDT #
Posted by Simon on August 21, 2006 at 10:36 PM PDT #
Posted by Karsten Wagner on August 22, 2006 at 05:32 AM PDT #
Closures aren't just syntactic sugar for anonymous inner classes. They might be implemented that way, but conceptually they are very different. - There is an important conceptual difference between
return new Iterator(){
hasNext(){...}
next(){...}
...
};
and
obj.addWhateverListener(new WhateverListener(){
public void whatever(Argument a){...}
});
To me, the first example is what anonymous classes should be used for - things which are used as objects, not overweight function pointers or callbacks. The other important difference between anonymous classes and closures is that closures have full access to the enclosing scope's variables. Karsten Wagner's suggestion of putting transient on local variables, which are then syntactic sugared into 1 element arrays seems a good one to me, although I'd say just let the compiler detect the usage as it does now and do the conversion on its own.
Basically, you can do closures in current java, but you have to use the extra verbose anonymous inner class syntax, which specifies all sorts of unneeded information - in the listener example, you state that this is a "whatever" callback 3 separate times - once in the function call seems enough to me. You also have the odd final requirement - why not just have the exact same effect as 1 element arrays?
Posted by Ben on August 22, 2006 at 06:49 AM PDT #
Posted by EricR on August 22, 2006 at 02:59 PM PDT #
I have logged a request for an enhancement to Java for shorter syntax for common operations. One of these common operations is anonaymous inner classes. Which as many people have pointed out have much in common with closures and first class functions. The aim of the proposed syntax changes are to remain backwards compatible with existing Java and provide a natural progression towards shorter syntax.
You can vote for and see detail of the proposal at:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6389769
The example from Neil Gafter's blog:
public static void main(String[] args) {
int plus2(int x) { return x+2; }
int(int) plus2b = plus2;
System.out.println(plus2b(2));
}
Would be with my proposal:
public static void main(String[] args) {
var plus2b = Object() int e(int x) return x+2;
System.out.println(plus2b.e(2));
}
Which seems very competative in terms of syntax and is a much less radical proposal and yet also has many other usage examples, including every variable delaration! Another example is, closure, instead of the current:
textField.addActionListner( new ActionListener() {
public void actionPerformed( ActionEvent notUsed ) {
textArea.append( textField.getText() );
}
});
You could write with my proposal:
textField.addActionListner( ActionListener() ( notUsed ) textArea.append( textField.getText() ); );
What do people think - is this a less radical alternative, yet achieves more? In particular simplifying many declarations not just closures and first class functions.
Posted by Howard Lovatt on August 22, 2006 at 10:26 PM PDT #
Posted by Paul Holser on August 23, 2006 at 06:22 AM PDT #
Runnable r = { System.out.println("hello"); }
transform(list, (T o) { return t.getColor(); });
This should be equivalent to:
Runnable r = new Runnable() {
void run() { System.out.println("hello"); }
}
transform(list, new Transformer<T> {
U transform(T t) { return t.getColor(); }
});
Posted by Stepan Koltsov on August 24, 2006 at 07:46 AM PDT #
Posted by fun on August 24, 2006 at 11:58 AM PDT #
Posted by Cláudio Gualberto on August 24, 2006 at 04:45 PM PDT #
Stepan Koltsov suggestion of simpler syntax is similar to my RFE:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6389769
The main difference between his propsal and mine is that he is adding some new syntax, I am proposing just making current compulsory bits optional. His examples, with the syntax I suggested are:
Runnable r = Runnable() () System.out.println( "hello" ); transform( list, Transformer< T >() ( t ) return t.getColor(); );
I think there is considerable advantage in just making the syntax shorter, rather than introducing new concepts that have at least some overlap with existing facilities. Furthermore innner classes have advantages:
In summary: closures are a poor man's inner class. Move on - it's a backward step.
Posted by Howard Lovatt on August 24, 2006 at 09:28 PM PDT #
Oops, the runable example should be:
var r = Runnable() () System.out.println( "hello" );
Posted by Howard Lovatt on August 24, 2006 at 09:33 PM PDT #
As an old functional programmer, I think first class closures sounds like the best thing since sliced bread (and a one-up on the delegates of That Other Language).
Mentioning delegates, it would seems consistent to allow turning methods into functions (i.e., delegates), e.g., by making an expression like (object.methodName) evaluate to a function. Instant delegates ... except that it can clash with a field of the same name, so some other syntax :(
There's one thing that I see missing: Recursive closures. Is there a way for a closure function to call itself? Perhaps something similar to function expressions in JavaScript (ex. (function omega(){omega()})(), where the name of the function is only visible inside the body).
Another thing I'd like to see for closures is proper tail recursion, something the JVM will probably have a very hard time supporting with its current feature set.
Or maybe I should just go back to ML :)
Regards
/L
PS. and I object to the word "closure" being used for the syntactic construct. I would personally prefer that being called a "function expression", and the value of that expression is then a closure. :)
Posted by Lasse Reichstein Nielsen on August 25, 2006 at 03:50 PM PDT #
Posted by Francis on August 26, 2006 at 09:26 PM PDT #
Posted by Stephen Colebourne on August 27, 2006 at 03:45 AM PDT #
Posted by Behrang on August 27, 2006 at 09:37 AM PDT #
<return_type> ( <args, ... )
public Object detect( boolean ( Object ) )
found = list.detect(
boolean ( Object each )
{
return each.equals( search );
} );
interface Something
{
boolean matches( Object arg );
}
found = list.detect( aSomething.matches );
Seems pretty simple to me.
>> it's too late to have them in Java cause methods like each,
>> etc. that use closures won't be added to Collection classes,
>> etc. as that would break compatibility...
Why would it break compatability?
R.
Posted by Robert DiFalco on August 27, 2006 at 01:19 PM PDT #
>>Why would it break compatability? R.
Because if I wrote a sub class of Collection (say something returned from a method that has to hold onto my object's state, like Map.values or Map.keySet), then my subclass of Collection needs to implement the method. This is one of the problems of using interfaces + single inheritance.
The solution for all of this sort of utility method is stuff like the Collections class, which holds all the methods that only need the Collection (or List/Map/Set) to be implemented. Each would have to be implemented like this, but it makes these utility methods second class citizens, which is why the extension methods someone mentioned above might be a good thing to include
Posted by Ben on August 27, 2006 at 01:26 PM PDT #
Posted by Mike Atkinson on September 09, 2006 at 01:48 PM PDT #
Posted by snoobab on September 12, 2006 at 02:12 AM PDT #
Well, I know it won't be compile-compatible if you add a new method to the Collection interface (you may still be able to modify it to a limited extent in other ways though) - you won't have implemented the method, and will therefore get an error. (If you always extend from AbstractCollection you might not run into problems, but you can't assume that).
What will happen if you try to use the old class files, I have no clue, but I would guess that it either breaks on the class verifier or something when loading, or throws a NoSuchMethodError when you try to call the new method.
Basically I'm saying that if I have (pretending Collection has nothing but add and get for simplicity)
public class Something {
public Collection<Thing> getThings(){
return new Collection(){
public void add(Thing it){ /* add it */}
public Thing get(int i){ /* return something */}
};
}
}
and then Java version x+1 adds the "void doStuff()" method to Collection, then my Collection subclass won't compile because it doesn't implement doStuff
Posted by Ben on September 12, 2006 at 05:54 PM PDT #
Posted by tuc on September 21, 2006 at 11:00 PM PDT #
Posted by Nishant Saini on September 24, 2006 at 06:34 AM PDT #