Sunday, July 14, 2013

Closure on Closures (examples in Javascript)

"Within the guilty closure of thy walls
Richard the Second here was hacked to death;
And, for more slander to thy dismal seat,


We give to thee our guiltless blood to drink
."
--Shakespeare, Richard III
Act III, Scene III, Lines 10-13

Question: "What is a closure?"




A closure is made up of the following

  • function
  • environment

Example with just Function and Environment



function makeHello() {
    var text = 'Hello';
    return function() {
        alert(text);
    }
}

function noFree() {
    var hello = makeHello();
    hello();
}


In the Javascript above, the function is the anonymous function returned from makeHello(), the environment is variable text with its value of Hello.

  • function => anonymous function returned from makeHello()
  • environment => variable text

Example with just Function and Environment, but more interesting


function makeCounter() {
    var counter = 0;
    return function() {
        alert(counter);
        counter++;
    }
}

var counter = makeCounter();
function counter() {
    counter();
}

In the Javascript above, the function is the anonymous function returned from makeCounter(), the environment is variable counter  with its value of 0 which incremented on each call to the anonymous function.

  • function => anonymous function returned from makeCounter()
  • environment => variable counter
Each call to anonymous function returned will give back a different value of counter.

var counter = makeCounter();
function counterTwice() {
    counter();  //0
    counter();  //1
}

Question: "What is a closure?"

Answer: "A poor man's class"


The two examples above do not give us anything we could not get with a class.

Example with a Free Variable


function makeAdder(toAdd) {
    return function(value) {
        return toAdd + value;
    }
}

In the Javascript above, the function is the anonymous function returned from makeAdder()and the environment is variable toAdd.

  • function => anonymous function returned from makeAdder()
  • environment => variable toAdd
Once the anonymous function is made the toAdd value is bound to the value passed in to the makeAdder() function, this value cannot be changed, but value the bound variable can be change on every call to the anonymous function.

var add5 = makeAdder(5);
function add5and2() {
    alert(add5(2)); //7
}
function add5and4() {
    alert(add5(4)); //9
}

Question: "What is a closure?"

Answer: "A function that can access non-local variables"


The example above should us how to use a closure to access non-local variables.

Example with a "Cache" and a FizzBuzz function


function makeFizzBuzz() {
    var map = {};
    return function(value) {
        if (map[value])
            return 'from mapper: ' + map[value];
        
        if (value % 15 === 0) {
            map[value] = 'FizzBuzz';
            return 'FizzBuzz';
        }
        else if (value % 3 === 0) {
            map[value] = 'Fizz';
            return 'Fizz';
        }
        else if (value % 5 === 0) {
            map[value] = 'Buzz';
            return 'Buzz';
        }
        else {
            map[value] = value.toString();
            return value.toString();
        }
    }
}

In the Javascript above, the function is the anonymous function returned from makeFizzBuzz()and the environment is dictionary map.

  • function => anonymous function returned from makeFizzBuzz()
  • environment => dictionary map
Once the anonymous function is made the dictionary map is bound to the function creating the environment that the anonymous function is executed in, the bound variable value can be change on every call to the anonymous function.  When the anonymous function is called a look up is done against the map, if the value is found it is returned to the caller, if it is not found the result is calculated and added to map and then returned to the caller, thus the environment in which the anonymous function is executing in is being enhanced with new information added to the dictionary.

function testFizzBuzzWith3() {
    var fizzBuzzer = makeFizzBuzz();
    alert(fizzBuzzer(3));
}

function testFizzBuzzFull() {
    var fizzBuzzer = makeFizzBuzz();
    alert('3 should be Fizz = ' + fizzBuzzer(3));
    alert('5 should be Buzz = ' + fizzBuzzer(5));
    alert('15 should be FizzBuzz = ' + fizzBuzzer(15));
    alert('1 should be 1 = ' + fizzBuzzer(1));
    alert('15 should be FizzBuzz from mapper = ' + fizzBuzzer(15));
    alert('9 should be Fizz = ' + fizzBuzzer(9));
    alert('25 should be Buzz = ' + fizzBuzzer(25));
    alert('30 should be FizzBuzz = ' + fizzBuzzer(30));
}

We see above that once the value 15 is passed to the anonymous function a later call to the same function with the value of 15 will be found in the dictionary.  This is known as the memorization pattern (other examples in F# or Haskell).

Question: "What is a closure?"

Answer: "A function that captures the environment in which it was created"

We see more fully now by the above example that a closure captures the environment in which it was created.

Examples are all on jsFiddle.

These site have really great examples: