Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

You have about 10 seconds to get his interest before he starts thinking about his WoW raid tonight, and about 5 minutes for the whole explanation.

Not going to happen. First, you need a person that wants to better themselves as a programmer, and understanding closures is just a part of that. Discounting the time it takes to put someone in that state of mind, closures can be explained in under a minute (edit: OK, maybe two minutes ;)).

A closure is just a (function, bindings) pair. If someone has a Java/C++ background, it might help to think of a closure as an object which has some code with references to variables defined outside of that code. Those variables are dependencies without which you can't run the code.

JavaScript example:

    function foo() {
        var x = 1;
        function bar() {
            return x + 1;
        }
        return bar;
    }
What does foo() return? It returns bar. But it can't just return bar, since bar has a dependency on x, so it returns bar and everything bar references: the closure (bar, { x: 1 }). In practice, you call a closure as you would call a function, but underneath the abstraction, you need to realize what's returned is both bar and the value of x.


So when does "x" get evaluated? What if x was a global variable instead? (Honest questions here, not trying to sidetrack the discussion. No, I don't "get" closures.)


Great question! Every time you call foo, a new scope containing x is created. That scope "travels" with bar, and is evaluated (dereferenced might be a better word) just as any other variable inside bar would be - during the execution of bar. A global variable is just a variable in the topmost ("global") scope.

But my example doesn't make the distinction to clarify that at all. Here's a better one:

    function colors() {
        var cs = ['red', 'green', 'blue'],
            i = 0;

        function nextcolor() {
            i = (i+1) % cs.length;
            return cs[i];
        }

        return nextcolor;
    }
Every time you call colors, a new local scope is created. Easiest way to think of scopes is as maps from strings to values. In this case, a new scope { cs: ['red', 'green', 'blue'], i: 0 } is created every time you calls colors. If the language didn't support closures, that scope would be destroyed when colors finishes execution, but in JS, that scope is bound to nextcolor and returned along with nextcolor in a closure. Now, every time you call a particular nextcolor returned by a call to colors, the cs and i variables will reference those same values. Example using firebug:

    >>> A = colors()
    >>> B = colors()
    >>> A() => "green"
    >>> A() => "blue"
    >>> B() => "green"
    >>> B() => "blue"
    >>> A() => "red"
    >>> A() => "green"
    ...
Keep asking if anything is unclear. I was wrong about this taking 1 minute, I suppose... :)


For the record: on second reading, I should have said "that scope is bundled with nextcolor and returned as a closure", not "bound to nextcolor", since the word "bound" is usually used to talk about variable names ("identifiers") and their values.

Similarly, in the next sentence, I should have pointed out that when you call the returned value, you're not just calling nextcolor but the closure over nextcolor, which includes the bindings for cs and i.


Your two javascript examples are fantastic. Thank you for explaining this in a very clear way.


If x was a global variable then you don't have a closure, just an anonymous function.

Closures require closed over variables.


>Closures require closed over variables.

Is "over variables" a term here? Is that the same as "upvalues"?


Yup, the "upvalues" of a closure are the dependencies of the function that the closure "closes over".

So in OO terms, the reason "bar closes over x" is because bar's execution has a dependency on the value of x. Since bar needs x to execute, we "close bar over x (and whatever other dependencies bar has)" to create the "closure".

To demonstrate some other uses, when we take "the closure [of|over] bar", we "close over bar", meaning "find all of bar's dependencies, and bundle them". The resulting closure is "closed over x", as well. I guess in this context "over" means "including". So you've got a bunch of references and a function laying around. You take a "closure" like you would a tarp or something, and put it "over" all that stuff. Now you've got the function and the references "closed over" by the "closure".

Personally, I think this terminology is a little weird and immediately intuitive to someone without a math background [1]. On the other hand, getting good at comprehending less-than-intuitive definitions seems to be a big part of CS and Math, so it's important to get used to it :)

1. There are "closed" things are all over mathematics, meaning vaguely similar things: http://en.wikipedia.org/wiki/Closed


Your explanation here is very, very helpful. I just copied and pasted it into a file for later reference. Thank you for taking the time to explain this!


Cool! Glad to be helpful :) I feel like I'm rephrasing the same thing a lot, but in hindsight, closures took me quite a bit of repetition/rephrasing to wrap my mind around. To fully grok them, you really need to have a clear understanding of how scope and variable references work.


Every time you call bar, x gets evaluated again. If x was a global variable, the same thing would happen.

Closures don't change the scope of any existing thing. What they do is force the program to keep scopes around because something still refers to them. Those scopes become a place to stick private data. If you create multiple functions in that scope, they can communicate through that private data. Here is a simple example in JavaScript.

  function closure_demo (x) {
      return {
           set: function (s) {x = s}
         , get: function () {return x}
      };
  }

  var foo = closure_demo("hello");
  var bar = closure_demo("world");

  alert("Bar is " + bar.get());
  alert("Foo is " + foo.get());

  foo.set("goodbye");
  bar.set("earthlings");

  alert("Bar is now " + bar.get());
  alert("Foo is now " + foo.get());
What is happening here? Each function call has a scope. We return an object with 2 functions that can access this scope. Each time you call the function you get a separate scope, so if you call it twice you get different closures. The scope must exist as long as those functions exist.


This is a good example of the problem with saying "closure" rather than "lexical scope". What most people mean by "closure" is a single anonymous function with state attached. What you've done here is returned an anonymous object containing two named functions.

So, it's obviously a closure because x is being "closed over". But if we're being pedantic it's actually not a closure. It's a lexically scoped anonymous object. And a closure is just an anonymous function, no more no less. A function in a language with lexical scope.


Sorry, but your attempted pedantry betrays some fundamental misunderstandings.

You claim that a closure is just an anonymous function, no more no less. But as http://en.wikipedia.org/wiki/Closure_%28computer_science%29 points out, this is a common misunderstanding that arises because people are introduced to the concepts at the same time. But the concepts of closures and anonymous functions really are distinct.

A closure is a function that closes over some lexical environment. Whether the function is named or not is irrelevant. In JavaScript if I type

  foo = some_function_that_returns_a_closure();
then foo winds up being a named function, but it is still a closure. Most languages require more gyrations to wind up with a named function. But dynamic languages that allow metaprogramming at run-time usually have some way to make a closure into a named function. For example:

  ; Scheme
  (define foo some_closure)
  
  # Perl
  *foo = $some_closure;

  ; Common Lisp
  (setf (symbol-function ’foo) #’some-closure)
Going the other way, anonymous functions are not always closures. What if you create an anonymous function outside of any lexical scope, it isn't a closure. What if you create an anonymous function in a language without the idea of lexical scope? Such languages exist. You can play with function pointers in C, anonymous functions in elisp (the Lisp built into emacs), and anonymous functions in vimsh (the scripting language built into vim) all you want but you won't get closures in those languages.

Now back to my example. I returned a data structure that had two closures that closed over the exact same lexical scope. The functions foo.set, foo.get, bar.set and bar.get are all closures. Since pairs of them share environments they can communicate through those environments. But the fact that they appear in a more complex data structure doesn't change the fact that they are closures. If you prefer you can pull them out into variables and manipulate them that way:

  var foo_set = foo.set;
  var foo_get = foo.get;

  // time passes
  foo_set("hello");
  alert(foo_get());
See? Closures!

Don't be confused by the fact that JavaScript built an object system on top of data structures with closures. That detail is a red herring. Anyways you've got data structures with cooperating closures, anyone can build object systems. It is easier than you might think, as pg demonstrated nicely in his book On Lisp. (In section 25.2 he implements a reasonable object system in just 2 pages of code.) And the people at Netscape who invented JavaScript had been around Lisp enough that doing so was a natural step for them.

The moral is that what matters are the mechanic Any function that has variables bound to a lexical scope is a closure. No matter what context it appears in. Whether it is named, part of an object, some other data structure, etc, it is still a closure.




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: