Sunday, November 21, 2010

JavaScript: eliminate temporary variables with higher-order functions

Functional Programming: it's the new cool! Any number of new languages striving to prove their functional programming credentials, and some old ones getting a boost. For most of it's life JavaScript has been trying to prove itself as an object oriented language, but you can also do some very neat functional programming style tricks with it. I think that the functional programming side of JavaScript is it's real strength.

So what's the big deal with FP? Didn't OO teach us that functions are the source of evil unstructured code? The FP response is that OO makes it too tempting to tinker with state, if you base you programming on storing and manipulating state then you will end up in a bad state sooner or later. Programming in an FP style often ends up with very little state and that state can be changed in only a very few places and narrow windows of time.

The following example uses a temporary variable to hold the current time and then makes an anonymous function to return it, the anonymous function is passed in turn as a parameter to another function. Old school procedural style code:

var temp = getTime();
fn1(function() { return temp; });

If you want to program in an FP style you've got to learn to find that temporary variable ugly, it's state, and it's an opportunity for mistakes. Your first instinct might be to inline the call to getTime() like this:

fn1(function() { return getTime(); });

But that would be wrong, getTime() is accessing changing state, the clock. The original code meant for it to be called just once when the anonymous function was first made. So we're going to isolate that call to changing state with something in a functional style:

function returner(x) { return function() { return x; } }
fn1(returner(getTime()));

Same functionality, no temporary variable. But it's not getting rid of the temporary variable that makes this functional programming, it's that I'm using a function that returns a function. That's the essence of higher-order programming: functions as the data that other functions work upon.

Things to notice: the helper function, returner() doesn't know anything about time, it's really just a tool for locking down some state, turning it into the return value of a function. Specifically we're using the stack to hold the state with the name x, and then we're closing on the value of x with an anonymous function so that we've still got access to it after the stack unwinds. As you do more in a functional programming style you might start building up a library of functions like these, and you'll discover that there are some standard functions that are effectively the patterns of the functional programming world, things like map, reduce, curry and others which I'll talk about in future.

One way to practice this is try writing your program with functions that have only one statement in the body, the return statement, and no var statements at all. All the work will be in the parameters you pass to your functions and what you can do in your return statements.

Take your time, this can be mind bending. You'll find as you apply this technique you'll have less need for variables and wrapper objects to hold state. Less state means less opportunity for errors because you can't be in a bad state. Having both the code organising benefits of OO and the state avoiding mindset of FP is a happy place for a programmer to be, and JavaScript give us that in a very simple package.

No comments:

Post a Comment