views:

1787

answers:

7
+4  A: 

Typically, if one doesn't have closures, one must define a class to carry with it the equivalent of the closure's environment, and pass it around.

For example, in a language like Lisp, one can define a function that returns a function (with a closed-over environment) to add some predefined amount to its argument thusly:

(defun make-adder (how-much)
  (lambda (x)
    (+ x how-much)))

and use it like this:

cl-user(2): (make-adder 5)
#<Interpreted Closure (:internal make-adder) @ #x10009ef272>
cl-user(3): (funcall * 3)     ; calls the function you just made with the argument '3'.
8

In a language without closures, you would do something like this:

public class Adder {
  private int howMuch;

  public Adder(int h) {
    howMuch = h;
  }

  public int doAdd(int x) {
    return x + howMuch;
  }
}

and then use it like this:

Adder addFive = new Adder(5);
int addedFive = addFive.doAdd(3);
// addedFive is now 8.

The closure implicitly carries its environment with it; you seamlessly refer to that environment from inside the executing part (the lambda). Without closures you must make that environment explicit.

That should explain to you when you would use closures: all the time. Most instances where a class is instantiated to carry with it some state from another part of the computation and apply it elsewhere are elegantly replaced by closures in languages which support them.

One can implement an object system with closures.

Rich
Thanks for your answer. Could you describe a code sample where it is effective to use closure?
shahkalpesh
A: 

In Lua and Python it's a very natural thing to do when "just coding", because the moment you reference something that's not a parameter, you're making a closure. (so most of these will be quite dull as examples.)

As for a concrete case, imagine an undo/redo system, where the steps are pairs of (undo(), redo()) closures. The more cumbersome ways of doing that might be to either: (a) Make unredoable classes have a special method with universally dorky arguments, or (b) subclass UnReDoOperation umpteen times.

Another concrete example is infinite lists: Instead of working with genericized containers, you frob a function that retrieves the next element. (this is part of the power of iterators.) In this case you can either keep just little bit of state (the next integer, for the list-of-all-nonnegative-integers or similar) or a reference to a position in an actual container. Either way, it's a function that references something that is outside itself. (in the infinite-list case, the state variables must be closure variables, because otherwise they'd be clean for every call)

Anders Eurenius
Thanks for your answer. Could you describe a code sample where it is effective to use closure?
shahkalpesh
+15  A: 

I agree with a previous answer of "all the time". When you program in a functional language or any language where lambdas and closures are common, you use them without even noticing. It's like asking "what is the scenario for a function?" or "what is the scenario for a loop?" This isn't to make the original question sound dumb, rather it's to point out that there are constructs in languages that you don't define in terms of specific scenarios. You just use them all the time, for everything, it's second nature.

This is somehow reminiscent of:

The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said "Master, I have heard that objects are a very good thing - is this true?" Qc Na looked pityingly at his student and replied, "Foolish pupil - objects are merely a poor man's closures."

Chastised, Anton took his leave from his master and returned to his cell, intent on studying closures. He carefully read the entire "Lambda: The Ultimate..." series of papers and its cousins, and implemented a small Scheme interpreter with a closure-based object system. He learned much, and looked forward to informing his master of his progress.

On his next walk with Qc Na, Anton attempted to impress his master by saying "Master, I have diligently studied the matter, and now understand that objects are truly a poor man's closures." Qc Na responded by hitting Anton with his stick, saying "When will you learn? Closures are a poor man's object." At that moment, Anton became enlightened.

(http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg03277.html)

Brian
Nice.Since functional programming is different (in the sense of managing state), it is natural to use closures. I do not have much background in functional programming. I use c#, it introduces this concept. An example would still be appreciated.
shahkalpesh
Looking at the analogy you gave (since FP doesnt have a concept of object), the state is passed around from a function to another function and thereby a state of the entire application is managed.right?
shahkalpesh
In pure FP, you usually don't care about state at all. When you do need state, you make it explicit and pass it around.
Matthias Benkard
… and Common Lisp isn't pure FP: it has mutable state. You just have a huge choice of ways to work with state :)
Rich
Common Lisp has CLOS (Common Lisp Object System), the most elaborate function parameter and return passing system I know, tail call optimization, the extended LOOP ... It is much more versatile than all those "pure" (narrow minded?) languages, and it still has this well defined, consistent syntax.
Svante
I don't get the Zen story? How is it they're each other's poor man's compliments?
zvolkov
+2  A: 

The most simple example of using closures is in something called currying. Basically, let's assume we have a function f() which, when called with two arguments a and b, adds them together. So, in Python, we have:

def f(a, b):
    return a + b

But let's say, for the sake of argument, that we only want to call f() with one argument at a time. So, instead of f(2, 3), we want f(2)(3). This can be done like so:

def f(a):
    def g(b): # Function-within-a-function
        return a + b # The value of a is present in the scope of g()
    return g # f() returns a one-argument function g()

Now, when we call f(2), we get a new function, g(); this new function carries with it variables from the scope of f(), and so it is said to close over those variables, hence the term closure. When we call g(3), the variable a (which is bound by the definition of f) is accessed by g(), returning 2 + 3 => 5

This is useful in several scenarios. For example, if I had a function which accepted a large number of arguments, but only a few of them were useful to me, I could write a generic function like so:

def many_arguments(a, b, c, d, e, f, g, h, i):
    return # SOMETHING

def curry(function, **curry_args):
    # call is a closure which closes over the environment of curry.
    def call(*call_args):
        # Call the function with both the curry args and the call args, returning
        # the result.
        return function(*call_args, **curry_args)
    # Return the closure.
    return call

useful_function = curry(many_arguments, a=1, b=2, c=3, d=4, e=5, f=6)

useful_function is now a function which only needs 3 arguments, instead of 9. I avoid having to repeat myself, and also have created a generic solution; if I write another many-argument function, I can use the curry tool again.

zvoase
+18  A: 

Closures are simply great tools. When to use them? Any time you like... As has already been said, the alternative is to write a class; for example, pre C# 2.0, creating a parameterised thread was a real struggle. With C# 2.0 you don't even need the `ParameterizedThreadStart' you just do:

string name = // blah
int value = // blah
new Thread((ThreadStart)delegate { DoWork(name, value);}); // or inline if short

Compare that to creating a class with a name and value

Or likewise with searching for a list (using a lambda this time):

Person person = list.Find(x=>x.Age > minAge && x.Region == region);

Again - the alternative would be to write a class with two properties and a method:

internal sealed class PersonFinder
{
    public PersonFinder(int minAge, string region)
    {
        this.minAge = minAge;
        this.region = region;
    }
    private readonly int minAge;
    private readonly string region;
    public bool IsMatch(Person person)
    {
        return person.Age > minAge && person.Region == region;
    }
}
...
Person person = list.Find(new PersonFinder(minAge,region).IsMatch);

This is fairly comparable to how the compiler does it under the bonnet (actually, it uses public read/write fields, not private readonly).

The biggest caveat with C# captures is to watch the scope; for example:

        for(int i = 0 ; i < 10 ; i++) {
            ThreadPool.QueueUserWorkItem(delegate
            {
                Console.WriteLine(i);
            });
        }

This might not print what you expect, since the variable i is used for each. You could see any combination of repeats - even 10 10's. You need to carefully scope captured variables in C#:

        for(int i = 0 ; i < 10 ; i++) {
            int j = i;
            ThreadPool.QueueUserWorkItem(delegate
            {
                Console.WriteLine(j);
            });
        }

Here each j gets captured separately (i.e. a different compiler-generated class instance).

Jon Skeet has a good blog entry covering C# and java closures here; or for more detail, see his book C# in Depth, which has an entire chapter on them.

Marc Gravell
Slightly off-topic, but could you suggest how to pronounce "Person person = list.Find(x=>x.Age > minAge " if read aloud?
Dour High Arch
"assign variable person (of type Person) with list.Find: x goes to x.Age greater than minAge and x.Region equals region". Although I'd probably abbreviate to: "...with list.Find where Age greater than minAge and Region equals region.". But "goes to" is a common interpretation of "=>".
Marc Gravell
Regarding this, you might be interested in answering http://stackoverflow.com/questions/1962539/using-closures-to-keep-track-of-a-variable-good-idea-or-dirty-trick :)
RCIX
I think the common pronunciation of the '=>' operator is "given". For example, 'p=>p.name' would be read "given p, p-dot-name".
Stimul8d
@Stimul8d - I've *never* heard it called that, but each to their own.
Marc Gravell
+1  A: 

Here is an example from Python's standard library, inspect.py. It currently reads

def strseq(object, convert, join=joinseq):
    """Recursively walk a sequence, stringifying each element."""
    if type(object) in (list, tuple):
        return join(map(lambda o, c=convert, j=join: strseq(o, c, j), object))
    else:
        return convert(object)

This has, as parameters, a convert function and a join function, and recursively walks over lists and tuples. The recursion is implemented using map(), where the first parameter is a function. The code predates the support for closures in Python, so needs two additional default arguments, to pass convert and join into the recursive call. With closures, this reads

def strseq(object, convert, join=joinseq):
    """Recursively walk a sequence, stringifying each element."""
    if type(object) in (list, tuple):
        return join(map(lambda o: strseq(o, convert, join), object))
    else:
        return convert(object)

In OO languages, you typically don't use closures too often, as you can use objects to pass state - and bound methods, when your language has them. When Python didn't have closures, people said that Python emulates closures with objects, whereas Lisp emulates objects with closures. As an example from IDLE (ClassBrowser.py):

class ClassBrowser: # shortened
    def close(self, event=None):
        self.top.destroy()
        self.node.destroy()
    def init(self, flist):
        top.bind("<Escape>", self.close)

Here, self.close is a parameter-less callback invoked when Escape is pressed. However, the close implementation does need parameters - namely self, and then self.top, self.node. If Python didn't have bound methods, you could write

class ClassBrowser:
    def close(self, event=None):
        self.top.destroy()
        self.node.destroy()
    def init(self, flist):
        top.bind("<Escape>", lambda:self.close())

Here, the lambda would get "self" not from a parameter, but from the context.

Martin v. Löwis
A: 

This article includes two examples of where closures are actually useful: Closure

mikej