A Systems Analyst's thoughts on science, technology, programming, business, and occasionally politics.

Closures

September 25, 2008 at 2:57 pm | In Technology | No Comments
by Chris Davenport

This weekend, I learned about closures. Part of this has to do with the fact that I seem to be obsessed with StackOverflow.com; it was there that I found a question on closures with a link to an answer, and prompted my fire of discovery to go learn about them.

Closures are Functions-with-context. Usually used in formal proofs and the like, but also used in functional programming languages like Haskell. Languages like C are called imperative because they focus more on step-by-step action.

Anyway, the neat thing about a closure is persistence, or maybe independence, depending on how you think about it.

In standard C, I might call a function:

do_stuff(with_stuff)
{
    coefficient = 3;
    some_var = rand();
    new_stuff = with_stuff * with_stuff + with_stuff / some_var;
    return new_stuff * coefficient;
} 

And the compiler will create a stack frame to call the function.. pushing some saved state onto the stack if needed, a return address, then with_stuff. Then the local variables to the function will be allocated on the stack, here they’re some_var, coefficient, and new_stuff.

When the function returns, it places new_stuff in the stack, or puts it in a register, and then returns, and the stack frame is lost. All the local variables are gone, popped off the stack. Really they’re still present, but the stack pointer is now indicating that space is available, so the next push, or sometimes the push of the return value, will overwrite them. They’re not persistent.

But they are the context of the do_stuff function. If you wanted to call it remotely on another machine, that’s all the data that you’d need to pass around and/or allocate on the remote side. If the language supports closures, then this is the neat little package that is all about “do_stuff(with_this_stuff)”.

JavaScript, as it turns out, contains closures. They’re a bit tricky to get to, but they exist. Basically, any time you create a function, you get a closure.

I don’t mean the regular function do_stuff(with_stuff) like we did before. I mean really create one. So you can modify the previous do_stuff function so that it doesn’t actually do stuff, it just returns a function that will do the stuff when you ask it to later. Kind of a cool way to defer execution and evaluation.

do_stuff(with_stuff)
{
    coefficient = 3;
    some_var = rand();
    do_func = function() {
        new_stuff = with_stuff * with_stuff + with_stuff / some_var;
        return new_stuff * coefficient;
    }

    return do_func;
}

When you’re thinking about it, you may notice that coefficient and some_var were declared, allocated, and assigned within do_stuff.. But do_func is returned, and therefore would exist after coefficient and some_var are lost. The interpreter keeps the stack frame from do_stuff around as a closure for do_func, so that when you call do_func later, it has valid references to coefficient and some_var.

And it’s unique. If you call do_stuff again, you’ll get a new do_func returned, with it’s own reference to a new stack frame from do_stuff, and it’s own closure.

Now comes the really fun stuff. Since we have a function closure in a variable, we know we can call it later. We can even build up a bunch of them and execute them more in parallel. What’s interesting is calling it multiple times. The same closure is used for all invocations. so if we call our returned do_func() once, and then call it again, some_var will actually have the same value. It was assigned just once, randomly, when we called do_stuff, then made part of the closure, and is now persistent.

And then there were two. You could, conceivably, create more than one function this way, even inside the same do_stuff function, and they’d share one closure, both able to access the same out-of-scope variables from the creating context.

Perl can do the same thing; they’re very similar languages.

No Comments yet »

RSS feed for comments on this post. TrackBack URI

Leave a comment

XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>