63

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

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
koen
  • 13,349
  • 10
  • 46
  • 51

10 Answers10

77

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
  • 243,077
  • 51
  • 345
  • 550
  • I think it is the other way around: a class is a generalization of a closure. A closure is just one function that has access to a bunch of state, but a class has many methods which share access to the same state. Many languages (e.g. Java, Python, etc.) have local classes, which can capture variables from surrounding scope just like a closure; so they are strictly more general than closures. – newacct Nov 08 '11 at 05:45
  • 3
    @newacct: not at all. You can easily create multiple functions with the same closure. Just create them in the same place, and they'll capture the same variables. But as I said, a closure captures "anything visible here", whereas a class method captures "anything that is visible here *and which is in the class*. Of course, I'm not talking about local classes, which really don't have much to do with "regular" classes. – jalf Nov 08 '11 at 08:10
  • @jalf so. Method is a closure ? – hqt Feb 10 '16 at 20:00
31

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
  • 7,231
  • 1
  • 26
  • 29
  • 10
    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 Aug 20 '09 at 11:47
  • 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 Aug 20 '09 at 11:50
  • 19
    If style/readability isn't power, then we would be able to write any application in the world with punchcards. – Mark Seemann Aug 20 '09 at 11:52
  • 1
    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 Aug 20 '09 at 11:57
  • Actually, in Java you can reach any variable in the current scope from the actionPerformed(...) method if you declare them final. – Viktor Sehr Aug 20 '09 at 12:41
  • 3
    @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 Aug 20 '09 at 14:56
  • 7
    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 Sep 17 '09 at 14:36
  • 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 Oct 09 '09 at 22:57
  • 41
    This seems like an example of first-class functions, not of closures. Closures also imply variable capture. – JW. Oct 09 '09 at 23:16
  • 6
    How is the example a closure? I thought closures had to reference variables from the enclosing scope... – recursive Oct 11 '09 at 00:55
  • @Gregory, it seems to me this is more an example of by-name parameters. Perhaps if the code you were passing to the addActionListener used a variable from the scope of the caller it would better demonstrate the essence of a closure – ThaDon Mar 24 '11 at 02:00
  • An anonymous inner class is also a closure in disguise. http://c2.com/cgi/wiki?ClosuresAndObjectsAreEquivalent – Daniel Yokomizo Aug 29 '13 at 14:57
  • Interestingly enough, to any budding developers making their way through the trenches right now trying to get enlightenment, Java 8, at the time of writing this, now does support closures: https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html – Alfredo Gallegos Jun 20 '16 at 21:54
31

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";
  $.ajax('/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.
  • 50,691
  • 36
  • 115
  • 143
  • 1
    I'm sorry, but what I see here is a real world anti-pattern. Defining a function within and object within a parameter list of a function invocation => poor readability. And when someone finally realizes that it makes more sense to pass requestID as a parameter, you will have a nice "sometimes" bug which will be hard to trace. The anonymous function will have the wrong ID only when the ajax call hasn't come back before the next request. Honestly, the traditional way of doing this is better for readability, robustness, and I really wonder if the performance is so much better with a closure. –  Aug 03 '13 at 03:07
  • I agree that defining the function within the parameter list isn't necessary -- that's just how I happened to write the example. Defining it within the other function is the point. Passing the requestID as a parameter is often not an option. For example, if you're using a third-party library to make the request, you can't control how it calls your callback function. – JW. Aug 03 '13 at 16:22
  • I'm sorry, I confused something. If the function gets called multiple times, the execution context won't be the same actually. I was mixing up with the problems one gets with loops and closures. –  Aug 07 '13 at 03:21
5

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
  • 1,328
  • 8
  • 11
  • 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 Aug 20 '09 at 11:57
  • 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 Aug 20 '09 at 12:01
  • 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 Aug 20 '09 at 12:16
  • 1
    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 Oct 09 '09 at 23:43
5

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
  • 3,130
  • 22
  • 24
3

Here are some interesting articles:

Jesper
  • 202,709
  • 46
  • 318
  • 350
3

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
0

As to the concluding query: "Do (closures) fit in an OO world?"

In many languages, closures, along with first-class functions, provide the very foundation for devising OO programs: Javascript, Lua and Perl come to mind.

In another more "traditional" OO language with which I'm familiar, Java, there are 2 primary differences:

  1. Functions are not first class constructs
  2. In Java the implementation details of OO (whether closures are used internally) is not exposed directly to the developer as it is in Javascript, Lua and Perl

Therefore in a "traditional OO" language such as Java, the addition of closures is largely just so much syntactic sugar.

Dexygen
  • 12,287
  • 13
  • 80
  • 147
-2

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
-2

looking at above examples, I can add my bit.

  • I appreciate the style, state-hiding part and chaining of expression but this is not enough

  • A lot can be said about simple and explicit code

  • I feel that Scala, Perl and some other Scheme type languages are designed to make kind of a shorthand for the particular way of thinking by the language designer or make them "more productive"

I would take the simplicity of python and early syntax of java etc as better way of simplicity and explicitness

It might be quite fast to write cryptic chained closures in a tight space. however everything can be done by simple objects and algorithms

closures are needed but not that often to warrant them to be first class citizen .

sdsadsadsada
  • 221
  • 2
  • 3
  • Indeed. You can write an object system with garbage collection in c. c is only a short abstraction away from assembler. But how easy is it to write and maintain? Abstractions are useful. Abstractions that are designed into a language are said to be *reified*. The question of "are closures needed?" is IMHO, the wrong question. I think the question should be, "can one write expressive, shorter and/or clearer code with closures?" – Chris Scott Sep 03 '13 at 13:11
  • When I see something like: "c is only a short abstraction away from assembler" I know for sure I am listening to someone who has never touched assembler. They are 2 VERY different languages. – Jason Webb Nov 07 '13 at 17:28