tags:

views:

1738

answers:

15

I've been reading a lot lately about the next release of Java possibly supporting closures. I feel like I have a pretty firm grasp on what closures are, but I can't think of a solid example of how they would make an Object-Oriented language "better". Can anyone give me a specific use-case where a closure would be needed (or even preferred)?

+31  A: 

The most obvious thing would be a pseudo-replacement for all those classes that just have a single method called run() or actionPerformed() or something like that. So instead of creating a Thread with a Runnable embedded, you'd use a closure instead. Not more powerful than what we've got now, but much more convenient and concise.

So do we need closures? No. Would they be nice to have? Sure, as long as they don't feel bolted on, as I fear they would be.

jodonnell
Thanks for reinforcing my suspicion that closures would just be syntactic sugar for anonymous inner classes.
Bill the Lizard
If they were as complete as JavaScript/C#/C++0x closures, they would be more powerful than anonymous inner classes, because they would be able to capture modifiable references to local variables, not just readonly copies of finals.
Daniel Earwicker
@Daniel Earwicker: You can simulate this by wrapping the modifiable variable in a container object (putting it on the heap) which is then assigned to a local final var.
Bart van Heukelom
@Bart van Heukelom - you can indeed, or even better, you can use a language that does this for you! :)
Daniel Earwicker
+16  A: 

I suppose for supporting core functional programming concepts, you need closures. Makes the code more elegant and composable with the support for closures. Also, I like the idea of passing around lines of code as parameters to functions.

Gulzar
Agreed, just for convenient map/filter implementations it would be worth it. Not to mention most uses of anonymous inner classes. Readability and code size counts.
Boris Terzic
+1  A: 

Java Closure Examples

J.F. Sebastian
It is the first link return by google search for *java closure example*
J.F. Sebastian
+31  A: 

They don't make an Object-Oriented language better. They make practical languages more practical.

If you're attacking a problem with the OO hammer - represent everything as interactions between objects - then a closure makes no sense. In a class-based OO language, closures are the smoke-filled back rooms where stuff gets done but no one talks about it afterwards. Conceptually, it is abhorrent.

In practice, it's extremely convenient. I don't really want to define a new type of object to hold context, establish the "do stuff" method for it, instantiate it, and populate the context... i just want to tell the compiler, "look, see what i have access to right now? That's the context i want, and here's the code i want to use it for - hold on to this for me 'till i need it".

Fantastic stuff.

Shog9
+3  A: 

Java has had closures since 1.1, just in a very cumbersome and limited way.

They are often useful wherever you have a callback of some description. A common case is to abstract away control flow, leaving the interesting code to call an algoritm with a closure that has no external control flow.

A trivial example is for-each (although Java 1.5 already has that). Whilst you can implement a forEach method in Java as it stands, it's far too verbose to be useful.

An example which already makes sense with existing Java is implementing the "execute around" idiom, whereby resource acquisition and release is abstracted. For instance, file open and close can be done within try/finally, without the client code having to get the details right.

Tom Hawtin - tackline
+2  A: 

As a java developer who is trying to teach themselves lisp in an attempt to become a better programmer, I would say that I would like to see the Josh Block proposal for closures implemented. I find myself using anonymous inner classes to express things like what to do with each element of a list when aggregating some data. To would be nice to represent that as a closure, instead of having to create an abstract class.

l0st3d
By "abstract class" you mean aonymous inner class?
Tom Hawtin - tackline
I *think* this is the proposal you're referring to. http://docs.google.com/Doc.aspx?id=k73_1ggr36h
Bill the Lizard
yes, Tom - I do mean that - sorryAnd that looks like it Bill - thanks
l0st3d
+5  A: 

Java doesn't need closures, an Object oriented language can do everything a closure does using intermediate objects to store state or do actions (in Java's case inner classes). But closures are desirable as a feature because they greatly simplify the code and increase readability and as a consequence the maintainability of the code.

I'm no Java specialist but I'm using C# 3.5 and closures are one of my favorite features of the language, for example take the following statement as an example:

// Example #1 with closures
public IList<Customer> GetFilteredCustomerList(string filter) {
    //Here a closure is created around the filter parameter
    return Customers.Where( c => c.Name.Contains(filter)).ToList();
}

now take an equivalent example that doesn't use closures

//Example #2 without closures, using just basic OO techniques
public IList<Customer> GetFilteredCustomerList(string filter) {
    return new Customers.Where( new CustomerNameFiltrator(filter));
}
... 
public class CustomerNameFiltrator : IFilter<Customer> {
    private string _filter;
    public  CustomerNameFiltrator(string filter) {
         _filter = filter;
    }
    public bool Filter(Customer customer) {
        return customer.Name.Contains( _filter);
    }
}

I know this is C# and not Java but the idea is the same, closures are useful for conciseness, and make code shorter and more readable. Behind the scenes, the closures of C# 3.5 do something that's looks very similar to example #2 meaning the compiler creates a private class behind the scenes and passes the 'filter' parameter to it.

Java doesn't need closures to work, as a developer you don't need them either, but, they are useful and provide benefits so that means that they are desirable in a language that is a production language and one of it's goals is productivity.

Pop Catalin
note that the difference is much smaller when you use anonymous classes
Michael Borgwardt
+6  A: 

There are some very useful 'higher order functions' which can do operations on lists using closures. Higher order functions are functions having 'function objects' as parameters.

E.g. it is a very common operation to apply some transformation to every element in a list. This higher order function is commonly called 'map' or 'collect'. (See the *. spread operator of Groovy).

For example to square each element in a list without closures you would probably write:

List<Integer> squareInts(List<Integer> is){
   List<Integer> result = new ArrayList<Integer>(is.size());
   for (Integer i:is)
      result.add(i*i);
   return result;
}

Using closures and map and the proposed syntax, you could write it like that:

is.map({Integer i => i*i})

(There is a possible performance problem here regarding boxing of primitive types.)

As explained by Pop Catalin there is another higher order function called 'select' or 'filter': It can be used to get all the elements in a list complying to some condition. For example:

Instead of:

void onlyStringsWithMoreThan4Chars(List<String> strings){
   List<String> result = new ArrayList<String>(str.size()); // should be enough
   for (String str:strings)
      if (str.length() > 4) result.add(str);
   return result;
}

Instead you could write something like

strings.select({String str => str.length() > 4});

using the proposal.

You might look at the Groovy syntax, which is an extension of the Java language to support closures right now. See the chapter on collections of the Groovy User Guide for more examples what to do with closures.

A remark:

There is perhaps some clarification needed regarding the term 'closure'. What I've shown above are strictly spoken no closures. They are just 'function objects'. A closure is everything which can capture - or 'close over' - the (lexical) context of the code surrounding it. In that sense there are closures in Java right now, i.e. anonymous classes:

Runnable createStringPrintingRunnable(final String str){
    return new Runnable(){
       public void run(){
          System.out.println(str); // this accesses a variable from an outer scope
       }
    };
}
jrudolph
Upvoted for knowing (and explaining) the distinction between closures and functions as values
Logan Capaldo
+2  A: 

When closures finally arrive in Java, I will gleefully get rid of all my custom comparator classes.

myArray.sort( (a, b) => a.myProperty().compareTo(b.myProperty() );

...looks a helluva lot better than...

myArray.sort(new Comparator<MyClass>() {
   public int compare(MyClass a, MyClass b) {
      return a.myProperty().compareTo(b.myProperty();
   }
});
benjismith
A: 

Not only that benjismith, but I love how you can just do...

myArray.sort{ it.myProperty }

You only need the more detailed comparator you've shown when the natural language comparison of the property doesn't suit your needs.

I absolutely love this feature.

+2  A: 

I've been reading a lot lately about the next release of Java possibly supporting closures. I feel like I have a pretty firm grasp on what closures are, but I can't think of a solid example of how they would make an Object-Oriented language "better."

Well, most people who use the term "closure" actually mean "function object", and in this sense, function objects make it possible to write simpler code in certain circumstances such as when you need custom comparators in a sort function.

For example, in Python:

def reversecmp(x, y):
   return y - x

a = [4, 2, 5, 9, 11]
a.sort(cmp=reversecmp)

This sorts the list a in reverse order by passing the custom comparison functoin reversecmp. The addition of the lambda operator makes things even more compact:

a = [4, 2, 5, 9, 11]
a.sort(cmp=lambda x, y : y - x)

Java does not have function objects, so it uses "functor classes" to simulate them. In Java you do the equivalent operation by implementing a custom version of the Comparator class, and passing that to the sort function:

class ReverseComparator implements Comparator {
   public compare(Object x, Object y) {
      return (Integer) y - (Integer) x;
   }

...

List<Integer> a = Arrays.asList(4, 2, 5, 9, 11);
Collections.sort(a, new ReverseComparator());

As you can see, it gives the same effect as closures, but is clumsier and more verbose. However, the addition of anonymous inner classes obviates most of the pain:

List<Integer> a = Arrays.asList(4, 2, 5, 9, 11);
Comparator reverse = new Comparator() {
   public Compare(Object x, Object y) {
       return (Integer) y - (Integer) x;
   }
}
Collections.sort(a, reverse);

So I would say that the combination of functor classes + anonymous inner classes in Java is sufficient to compensate for the lack of true function objects, making their addition unnecessary.

+22  A: 

As a Lisp programmer I would wish that the Java community understands the following difference: functions as objects vs. closures.

a) functions can be named or anonymous. But they can also be objects of themselves. This allows functions to be passed around as arguments, returned from functions or stored in data structures. This means that functions are first class objects in a programming language.

Anonymous functions don't add much to the language, they just allow you to write functions in a shorter way.

b) A closure is a function plus a binding environment. closures can be passed downwards (as parameters) or returned upwards (as return values). This allows the function to refer to variables of its environment, even if the surrounding code is no longer active.

If you have a) in some language, then the question comes up what to do about b)? There are languages that have a), but not b). In the functional programming world a (functions) and b (functions as closures) is nowadays the norm. Smalltalk had a) (blocks are anonymous functions) for a long time, but then some dialects of Smalltalk added support for b) (blocks as closures).

You can imagine that you get a slightly different programming model if you add functions and closures to the language.

From a pragmatic view the anonymous function adds some short notation where you pass or invoke functions. That can be a good thing.

The closure (function plus binding) allows you for example to create a function that has access to some variables (for example to a counter value). Now you can store that function in an object, access it and invoke it. The context for the function object is now not only the objects it has access to, but also the variables it has access to via bindings. This is also useful, but you can see that variable bindings vs. access to object variables now is an issue: when should be something a lexical variable (that can be accessed in a closure) and when should it be a variable of some object (a slot). When should something be a closure or an object? You can use both in the similar ways. A usual programming exercise for students learning Scheme (a Lisp dialect) is to write a simple object system using closures.

The result is a more complicated programming language and a more complicated runtime model. Too complicated?

Rainer Joswig
+2 if i could. This is the 'missing link' in discussions about java closures. Deserves a question of it's own, Rainer.
Bedwyr Humphreys
This is the best description of a closure that I have encountered. I understand now why the new closure implementation is being limited to local only. Danger Will Robinson, Danger!
WolfmanDragon
+1 Now I understand why Joshua Bloch says Java already has closures ( in the form of anonymous inner classes ) After reading what you said, I agree. The problems with a.i.c is they are way to verbose.
OscarRyz
+1  A: 

Closures in an imperative language (examples: JavaScript, C#, the forthcoming C++ refresh) are not the same as anonymous inner classes. They need to be able to capture modifiable references to local variables. Java's inner classes can only capture local final variables.

Almost any language feature can be criticised as non-essential:

  • for, while, do are all just syntactic sugar over goto/if.
  • Inner classes are syntactic sugar over classes with a field pointing to the outer class.
  • Generics are syntactic sugar over casts.

Exactly the same "non-essential" argument should have blocked the inclusion of all the above features.

Daniel Earwicker
Just to be clear, my question wasn't intended to argue in favor of blocking the inclusion of closures. Also, I would have agreed with the "non-essential" argument for one of the features you mentioned above. :)
Bill the Lizard
+2  A: 

A few people have said, or implied, that closures are just syntactic sugar - doing what you could already do with anonymous inner classes and making it more convenient to pass parameters in.

They are syntactic sugar in the same sense that Java is syntactic sugar for assembler (that "assembler" could be bytecode, for sake of argument). In other words they raise they level of abstraction, and this is an important concept.

Closures promote the concept of the function-as-object to a first class entity - one that increases the expressiveness of code, rather than cluttering it with even more boilerplate.

An example that's close to my heart has already been mentioned by Tom Hawtin - implementing the Execute Around idiom, which is just about the only way to get RAII into Java. I wrote a blog entry on exactly that subject a couple of years ago when I first heard closures might be coming.

Ironically, I think the very reason that closures would be good for Java (more expressiveness with less code) may be what rattles many Java advocates. Java has a mindset of "spell everything out the long way". That and the fact that closures are a nod towards a more functional way of doing things - which I also see as a Good Thing, but may water down the pure OO message that many in the Java community hold dear.

Phil Nash
I think "spell everything out the long way" would be more accurate as "spell everything out explicitly" (at least in my case). There is a subtle difference.
Bill the Lizard
Well - I'd say the two are distinct cases with a large intersection. So perhaps if we talk of the union of those two we get to the knub of it :-)
Phil Nash
First-class functions are a distinct idea from closures. The former refers to treating a reference to a function (or the function itself) as a value -- one that can be passed around and invoked at will. The latter is concerned with capturing references to values available lexically at the point of definition and extending their lifetime through the lifetime of the function created there. One can have first-class functions without having closures, though I don't think the converse makes sense.
seh
Well, they are distinct ideas, but one is based on the other (hence the lack of transitivity in your final comment). I said that, "Closures *promote* the concept of the function-as-object to a first class entity" - not that they were the same thing. The fact is, as it stands, Java does not have a proper concept of first class functions, but if it got Closures it would get that too as a pre-requisite. That's really what I meant. But if that wasn't clear it's good that you've clarified it with your comment :-)
Phil Nash
A: 

What about readability and maintainability...one-liner closures are harder to understand and debug, imo Software has looong life and you can get people with rudimentary knowledge of the language to maintain it...So spread out logic better than one-liners for easy maintenance...You generally don't have a software star looking after software after its release...

Neal Ravindran
Are you speaking from experience? My experience has been exactly the opposite.
Neal Gafter