views:

1038

answers:

9

As an OO developer, maybe I have difficulty seeing its value. What added value do they give? Do they fit in an OO world?

+10  A: 

Closures don't give you any extra power.

Anything you can achieve with them you can achieve without them.

But they are very usable for making code more clear and readable. And as we all know clean readable short code is a code that is easier to debug and contains fewer bugs.

Let me give you short Java example of possible usage:

    button.addActionListener(new ActionListener() {
        @Override public void actionPerformed(ActionEvent e) {
            System.out.println("Pressed");
        }
    });

Would be replaced (if Java had closures) with:

button.addActionListener( { System.out.println("Pressed"); } );
Gregory Mostizky
They don't give you any extra power - but they do give you extra style... I know I'd much rather write and read your second example than the former.If you go a step further and consider things like the map(), filter() and fold() methods in languageslike scala versus their java alternatives and the style becomes obvious
Martin
For your code example to be really fair, the NewActionListener should be a user-defined class as well. To emulate closures, you generally have to define a new class on the spot, just to capture the variables you need.
jalf
If style/readability isn't power, then we would be able to write any application in the world with punchcards.
Mark Seemann
Don't forget that closures capture variables in the local scope too. (To do this without closures you'd have to define a new class and pass the variables manually to the constructor)
Nick
Actually, in Java you can reach any variable in the current scope from the actionPerformed(...) method if you declare them final.
Viktor Sehr
@Nick, @Viktor: in Java, you can get read-only access to any variable in the current scope. With a true closure, you can get read-write access. Languages such as Scala provide "var" references that are read-write, versus "val" references that are read-only. Which goes a long way toward maintainable code.
kdgregory
Coming a bit late to the game on this one, but I will have to respectfully disagree that closures don't give you any extra power. In a multi-threaded environment, the ability to do a closure to capture a locally scoped variable in an anonymous function and then exit from the local scope while the anonymous function executes is *extremely* powerful.
Matt
Java would not allow that closure, the poster is assuming the the type within that closure, which is an ambiguity that java does not allow.
monksy
This seems like an example of first-class functions, not of closures. Closures also imply variable capture.
JW
How is the example a closure? I thought closures had to reference variables from the enclosing scope...
recursive
+4  A: 

IMHO it comes down to being able to capture blocks of code and their context to be referenced at some point later on and executed when/if/as required.

They may not seem to be a big deal, and closures definitely aren't something you need to get things done on a daily basis - but they can make code code much simpler and cleaner to write/manage.

[edit - code sample based on the comment above]

Java:

List<Integer> numbers = ...;
List<Integer> positives = new LinkedList<Integer>();
for (Integer number : integers) {
    if (number >= 0) {
        positives.add(number);
    }
}

Scala (skipping some of the other niceties like type inference and wildcards so we're only comparing the effect of the closure):

val numbers:List[Int] = ...
val positives:List[Int] = numbers.filter(i:Int => i >= 0)
Martin
Capturing context (in a read-write manner) is the reason that I don't like closures (as opposed to functions as first class objects): it increases the places where you can have unexpected state changes.
kdgregory
agreed - but with great power comes great responsibility... If you combine closures with as much immutability as possible you save yourself much of that pain, but it does take a bit of discipline (but then so does not abusing pretty much every aspect of C, so it's not impossible :])
Martin
I think that's why closures are so popular in functional languages: the side-effect-free structure of the language prevents stupid code. And in JavaScript, the rules governing enclosing context are so arcane that most people just pretend it doesn't exist.
kdgregory
Heh, not sure there is such a thing as 'prevents stupid code'.. Where there's a will there's a way, but I do get what yu're saying :)
RobS
+2  A: 

Here are some interesting articles:

Jesper
+13  A: 

You can see it as a generalization of a class.

Your class holds some state. It has some member variables that its methods can use.

A closure is simply a more convenient way to give a function access to local state.

Rather than having to create a class which knows about the local variable you want the function to use, you can simply define the function on the spot, and it can implicitly access every variable that is currently visible.

When you define a member method in a traditional OOP language, its closure is "all the members visible in this class".

Languages with "proper" closure support simply generalize this, so a function's closure is "all the variables visible here". If "here" is a class, then you have a traditional class method.

If "here" is inside another function, then you have what functional programmers think of as a closure. Your function can now access anything that was visible in the parent function.

So it's just a generalization, removing the silly restriction that "functions can only be defined inside classes", but keeping the idea that "functions can see whatever variables are visible at the point where they're declared".

jalf
+2  A: 

Closures fit pretty well into an OO world.

As an example, consider C# 3.0: It has closures and many other functional aspects, but is still a very object-oriented language.

In my experience, the functional aspects of C# tend to stay within the implementation of class members, and not so much as part of the public API my objects end up exposing.

As such, the use of closures tend to be implementation details in otherwise object-oriented code.

I use them all the time, as this code snippet from one of our unit tests (against Moq) shows:

var typeName = configuration.GetType().AssemblyQualifiedName;

var activationServiceMock = new Mock<ActivationService>();
activationServiceMock.Setup(s => s.CreateInstance<SerializableConfigurationSection>(typeName)).Returns(configuration).Verifiable();

It would have been pretty hard to specify the input value (typeName) as part of the Mock expectation if it hadn't been for C#'s closure feature.

Mark Seemann
+3  A: 

Maybe in the world of compiled programming the benefits of closures are less noticeable. In JavaScript closures are incredibly powerful. This is for two reasons:

1) JavaScript is an interpreted language, so instruction efficiency and namespace conservation are incredibly important for faster and more responsive execution from large programs or programs that evaluate large amounts of input.

2) JavaScript is a lambda language. This means in JavaScript functions are first class objects that define scope and scope from a parent function is accessible to child objects. This is important since a variable can be declared in a parent function, used in a child function, and retain value even after the child function returns. That means a variable can be reused by a function many times with a value already defined by the last iteration of that function.

As a result closures are incredibly powerful and provide superior efficiency in JavaScript.

A: 

The only real benefit of closures is to have smaller scopes and decrease memory consumption and items on the current stack.

Given that "benefit" it appears that closures would better be used as indicators where code needs to be refactored into smaller reusable bits.

monksy
+1  A: 

For me, the biggest benefit of closures is when you're writing code that starts a task, leaves the task to run, and specifies what should happen when the task is done. Generally the code that runs at the end of the task needs access to the data that's available at the beginning, and closures make this easy.

For example, a common use in JavaScript is to start an HTTP request. Whoever's starting it probably wants to control what happens when the response arrives. So you'll do something like this:

function sendRequest() {
  var requestID = "123";
  Ext.Ajax.request({
    url:'/myUrl'
    success: function(response) {
      alert("Request " + requestID + " returned");
    }
  });
}

Because of JavaScript's closures, the "requestID" variable is captured inside of the success function. This shows how you can write the request and response functions in the same place, and share variables between them. Without closures, you'd need to pass in requestID as an argument, or create an object containing requestID and the function.

JW
Very good example of real world usage of closures
Daniel Goldberg
+1  A: 

It's a pity, people no longer learn Smalltalk in edu; there, closures are used for control structures, callbacks, collection enumeration, exception handling and more. For a nice little example, here is a worker queue action handler thread (in Smalltalk):

|actionQueue|

actionQueue := SharedQueue new.
[
    [
        |a|

        a := actionQueue next.
        a value.
    ] loop
] fork.

actionQueue add: [ Stdout show: 1000 factorial ].

and, for those who cannot read Smalltalk, the same in JavaScript syntax:

var actionQueue;

actionQueue = new SharedQueue;
function () {
    for (;;) {
        var a;

        a = actionQueue.next();
        a();
    };
}.fork();

actionQueue.add( function () { Stdout.show( 1000.factorial()); });

(well, as you see: syntax helps in reading the code)

Edit: notice how actionQueue is referenced from inside the blocks, which works even for the forked thread-block. Thats what makes closures so easy to use.

blabla999