Get Functional


5 minute read


#Get Functional featureimage

##tl;dr

  • most of our programs are more complex than they have to be
  • functional approaches tend to result in code that:
  • is easier to read
  • has fewer source lines
  • is simpler
  • places fewer demands on the developer
  • simplicity is really difficult
  • watch this, use lodash, learn you haskell (or another functional language)

##Mmmm…Functional I’ve been on a bit of a functional kick for the past couple months and have really been loving the way taking a more functional approach has helped me reason through and improve my code. I won’t go into a long argument about why functional programming matters – which happens to be the name of a famous CS paper that is altogether more helpful on the topic; find it here.

Suffice to say that it generally allows developers to better reason through systems that don’t necessarily need to introduce all the mutable state that is often introduced (which is not to say that there’s never a time for mutable state, just that we use it way too often). For example:

var i,
  result = [];

for (i = 0; i < someArray.length; i++) {
  var someThing = someArray[i];
  if (someThing.isAwesome === true) {
    result.push(someArray[i]);
  }
}

Fairly straightforward, right? I see this sort of thing all the time. And for many cases, using loops is perfectly acceptable. For example, implementing an instertion sort algorithm usually requires that we use some combination of nested loops. For the most part, however, we really don’t have an absolute need to introduce all those variables. And once we start to deal with async requirements and the potential for callback hell, all this state can get difficult to keep track of.

This tends to be especially true when you get into a really complex app and you’re not just looping through some really simple array. You could use an awesome functional library like lodash to do something like:

var result = _.filter(someArray, function(someThing) {
  return someThing.isAwesome === true;
})

But you could also (and probably should) use some of the built-ins that JavaScript has available:

// returns an array of things that passed a test function
var result = foo.filter(someArray, function(someThing) {
  return someThing.isAwesome === true;
});

// returns a new array that you did stuff to
var result = foo.map(someArray, function(someThing) {
  return someThing.isAwesome();
});

// calls a function on every item in an array
var result = foo.forEach(someArray, function(someThing) {
  return ~~someThing;
});

// Applies a function against an accumulator and each value of the array
// has to reduce it to a single value.
var result = foo.reduce(someArray, function(someThing, anotherSomething) {
  return someThing + anotherSomething;
});

For other use-cases, lodash and it’s ancestor underscore can give you more fun methods to play with. Go npm install them. In my experience, when you do your best to remove state wherever appropriate and possible, you’ll finish and look at your code and be like…

Complexity || Simplicity

Aside from usually reducing the size of your code, there is another aspect to keeping things functional that you ought to consider: complexity. Keeping track of state is actually a very complex thing to do, both for us and for the machine. This isn’t to say it’s necessarily hard (especially not for the machine, that doesn’t really care until it runs out of memory), but only that there is actually a lot that goes into the lifecycle of mutable state. Allocation, persistence, setting, getting, typechecking, &c. I mean, even in the simplest possible for loop in JavaScript you end up introducing at least one extra variable just to make the loop happen – that’s not counting any other sorts of tracking you set up.

I really like the way that Rich Hickey has described complexity, as “how twisted up a thing is”. This is a great way to describe it because it completely leaves out any notion of difficulty or rightness or wrongness – it’s just structural analysis. This is great because not only does it satisfy Occam’s wonderful razor, but it can help you in something like code review –> it’s not “Your code is unreadble and terrible”, it’s “your code is overly complex and could be radically simplified”; things can be more in focus and less personal.

And no matter how brilliant a given developer may be, there are basic limits on the human brain that will run up against. You can only rememeber so many methods, variable names, and structures at a time and your short-term memory is far more limited at keeping track of things (7±2 things at any one time).

Why not make things simpler and avoid basic limits every developer will face? You can even use this as a factor in considering when and how to refactor. The other aspect of fighting complexity is that it ends up making you more truly agile. It’s pretty easy to grab a copy of frameworkX, but what about when the specs change and you don’t need frameworkX or your needs go beyond it? Or worse, what if you pulled down frameworkX to one thing when it can do 1,000?*cough jquery cough*. Anyone can pull down frameworkX – it’s so much more difficult to create something simple and elegant. True simplicity is the hardest work but the work with the highest possible payoff. Let’s close out some Rich Hickey goodness:

“Simplicity is hard work. But, there’s a huge payoff. The person who has a genuinely simpler system - a system made out of genuinely simple parts, is going to be able to affect the greatest change with the least work. He’s going to kick your ass. He’s gonna spend more time simplifying things up front and in the long haul he’s gonna wipe the plate with you because he’ll have that ability to change things when you’re struggling to push elephants around.” Rich Hickey

YES.

##Things to watch/use/learn:

Great things you can haz:

Great talk from the @scale conference on how functional reactive programming is used at Netflix to radically simplify async problems: