Closures

A closure is a phenomenon that occurs when lexical scope clashes with a first-class function.

First-Class Functions

High Class

In the Kingdom of Javaland, where King Java rules with a silicon fist, people aren't allowed to think the way you and I do. In Javaland, you see, nouns [objects] are very important, by order of the King himself. Nouns are the most important citizens in the Kingdom. They parade around looking distinguished in their showy finery, which is provided by the Adjectives, who are quite relieved at their lot in life. The Adjectives are nowhere near as high-class as the Nouns, but they consider themselves quite lucky that they weren't born Verbs [functions].

"First-class" means that functions can do all of the things you can do with the other citizens (e.g., Strings, Arrays, Booleans, or Numbers). This includes the ability to store functions in variables, pass them as arguments to other functions, and use them as return values from functions.

Examples of First-Class Functions

// Store a function in a variable. You could store any
// datatype in the `sayHi` variable, including a string,
// a boolean, or even a function!
var sayHi = function () {
  console.log("hi");
};
// Pass one function to another function. Here I'm passing
// two arguments to `setTimeout`: a Number and a Function.
// Meaning the Function is first-class, just like Number.
setTimeout(sayHi, 1000);
// You can even return a function from another function.
var outer = function () {
  console.log("i am outer");
  var inner = function () {
    console.log("i am inner");
  };
  return inner;
};
var result = outer(); // prints "i am outer"
result();             // prints "i am inner"

Lexical Scope

Lexical Scope

Scope determines what variables are visiable / available where.

var name = "Tim";
var sayHi = function () {
  console.log("Hi, my name is " + name);
};
sayHi(); // prints "Hi, my name is Tim"

How did that happen? There is no local variable called name inside of the sayHi() function. Due to lexical scoping, JavaScript was able to look into the surrounding _lexical environment_ to find the variable name.

Closures

Sometimes it's called a closure, other times a saved lexical environment. Or, as some of us like to say, _let over lambda_. Whatever terminology you use, mastering this concept of a closure is the first step to becoming a professional lisp programmer. In fact, this skill is vital for the proper use of many modern programming languages, even ones that don't explicitly contain let or lambda, such as Perl or JavaScript.

Patrick asks a question about closures

Patrick is pretty close to being correct. Actually, by some definitions, he may be correct. A function within a function does create the conditions for a closure, but you have to return the inner function from the outer one to get the benefit(s).

Step 1

Create an inner function within an outer function. Use lexical scope to access variable in outer scope from the inner scope. Easy peasy.

var outer = function () {

  var name = "Tim";

  var inner = function () {
    console.log("name is " + name);
  };

  inner();
};

outer();  // prints "name is Tim"
Step 2

Return the created function. First-class functions.

var outer = function () {

  var name = "Tim";

  var inner = function () {
    console.log("name is " + name);
  };

  return inner;
};
Step 3

Access variables from the outer function in the inner function after the outer function has returned. Closure.

var outer = function () {

  var name = "Tim";

  var inner = function () {
    console.log("name is " + name);
  };

  return inner;
};

var fn = outer();
fn(); // prints "name is Tim"

// This is a closure. It allows `name` to be available
// for use even outside of the `outer` function.

So, what?

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.