Tuesday 28 May 2013

The big deal about closures (and why you should think so too)

Whoa hey! You just stumbled onto my blog! Whether you came here by accident thinking this article is about how to get over that person who just left you, or by my devious design (muhahaha), feel free to read on..

So this article is about closures – functional closures to be more precise – a concept in functionally oriented languages that allows functions to hold onto state (in a nutshell).


Feeling dizzy already??
Here’s a little example from a little language we all know and love

function addN(n){
   var num1 = n;
   return function(num2){                //Returning a function !!
   return num1 + num2;
   };
}
var add1 = addN(1);
console.log(add1(2));
var add10 = addN(10);
console.log(add10(2));

The first most important thing to glean from this snippet is that in functionally oriented languages, functions are first-class citizens. So you can
·         return a function,
·         pass in a function as an argument,
·         store a function in a variable and invoke it,
·         and in some languages like javascript, you can even have properties on functions as they are ultimately objects
If you didn’t already know this, drill it into your brain…



Now that that’s out of the way, the code snippet clearly defines a function and
uses it in the last 4 lines. The function itself returns another function which is assigned to the variables add1 and add10 with values of ‘num1’ being 1 and 10 respectively…

But hang on… When add1(2) is called, isn’t ‘num1’ out of scope because addN has finished execution?

Here’s when the magic of closure comes, so hold on to your hats...
The variable num1 is still in scope because the returning function holds on to it, closing around it (Hence closure)... No one else can access it; it is only kept alive by the function, almost like a ghost imprint... [See 1 below]

So in this example add1 is a version (for lack of a better word) of addN with num1 = 1 and add10 is another one.
Let’s be clear: you can’t access either of the num1’s outside of the function code because it doesn’t exist. So add1.num1 doesn’t exist.
However the code inside the function can access num1. (Does this remind you of something?) [See 2 below]


So what does closure imply?
·         Closure implies scope (lifetime) [1]
·         Closure implies visibility (hence encapsulation) [2]
·         Closure implies shared and unshared state (unshared in this example, a demo of shared in an upcoming post)



So all that is neat, but what is it useful for?

So now we know that functions can carry around scope. They are essentially stateful (as compared to OO languages where they are stateless).

Functions in OO languages can access object state and operate on passed-in parameters but they themselves are stateless.


So functions in functional languages can have attached state and can access that state wherever it’s executing. Repeat, the function will continue to have that attached state wherever it’s executing. When a function is passed around and executed it will still have its initial scope and access to scope members.

The ability to do this is what sets functional languages apart and I cannot stress this enough.
Alex Russell of Google neatly puts it as
Instead of passing around objects which have state and happen to have behavior which can perform tasks on that state, we have behavior passed around which can operate on its associated state” [citation 1]

Steve Yegge also has a rant about this on his blog. That blog post was one of the finest pieces of literature I've ever read on a technical topic. [citation 2]

It isn't just another way to think or approach programming. There are actually some problems that cannot (or extremely tough to) be solved  by the traditional OO approach.


A demo of this in one of my upcoming posts so stay tuned…



Citations:

[1] Alex Russel talks about the good parts of javascript http://youtu.be/seX7jYI96GE?t=22m6s

[2] Steve Yegge's blog post : http://steve-yegge.blogspot.in/2006/03/execution-in-kingdom-of-nouns.html