close

Day 2: Every-day functional programming

Functional programming (FP) isn’t as hard or new as it sounds. It’s simply using the tools you’re already familiar with in different ways, and being conscious about aspects of your code you perhaps haven’t thought much about before. People are excited about FP because it leads to simpler code for most of the every-day tasks we face as programmers.

So what is FP? It’s a conscious focus on functions as our tool to abstract (organise tasks) and structure different our programs. You could say it’s old news – indeed the FP language Lisp has been around for 50+ years – but like many things in life, it’s the way you use the tools that explains how hard you’ll find solving a given problem.

Don’t panic

With FP there’s a lot to learn, and it can be hard to see the essential core behind the huge array of jargon. This article won’t be touching on exotic tools like monads and functors. Instead I’ll cover the core idea of using functions for abstraction and structure, and avoid confusing the issue with tools and techniques that don’t make practical sense in the context of Javascript.

Abstraction

Let’s take abstraction first. Abstraction allows us to deal with one problem at a time in our code, and is just as much a part of FP as Object-Oriented Programming (OOP).

Let’s consider splitting users in a real-time chat app into online and offline users. If we write this without higher-order functions we’ll end up with something like this:

var online = [];
var offline = [];

for(var i = 0, userCount = users.length; i < userCount; i++) {
  var user = users[i];
  if(user.online) {
    online.push(user);
  } else {
    offline.push(user);
  }
}

Here you can see our code solves two problems: the task of splitting a list by testing each item in each, and implementing a test to see if a user is online. One is common to every partition – the partitioning itself. The other – the test – is specific to each partition.

Let’s see what happens when we apply higher-order functions. The common part – splitting a list into a ‘yes’ and ‘no’ part – can be written as a function that accepts the specific part – the code that tests an item. Here’s what it’ll look like:

var usersByOfflineStatus = partition(users,function(user) {
  return user.online;
})

By passing a function to another function we can avoid duplicating the completely generic bit of a procedure – the partitioning – every time we need to partition, and simply write the bit we care about right now: the partitioning function.

It’s very easy to write partition. We take our original code, identify the parts which’ll change for each specific partition problem, and replace them with a function we pass into the partition:

function partition(list,test) {
    var groups = {yes: [], no: []}; 
    for(var i = 0, len = list.length; i < len; i++) {
      var item = list[i];
      // the test of this `if` statement is the only thing
      // specific to each partitioning problem
      if(test(item,i)) {
        groups.yes.push(item);
      } else {
        groups.no.push(item);
      }
    }
    return groups;
}

This is the algorithm (recipe) for converting any mixture of a common problem with a specific one. Identify what varies for each specific problem, and move those parts into arguments to a function that wraps up the common code. Now we’ve abstracted that common problem away the rest of our code is more coherent – focussing on solving problems at a higher level, closer to the specific task at hand.

If you think about how in OOP we specialise a generic superclass via overriding methods in subclasses, you should immediately see the similarity. In the FP version we are passing in the functions we’d override.

More higher-order functions

Higher-order functions are most applicable in day-to-day operations on lists and key-value objects (in JS we use objects {} for this, soon we’ll use Maps). If you take a peek at Array.prototype, you’ll see a gang of interesting higher-order functions to use in your programming. Let’s take a look at one.

It’s extremely common in programming to have a list of one type of thing, and to want to end up with a list of another. For instance: we have a list of users, and we’d like to extract how long they’ve been offline for.

Without higher order functions, we’d write this:

var offlineForMilliseconds = [];
for(var i = 0, userCount = users.length; i < userCount; i++) {
   var offlineMilliseconds = Date.now() - users[i].lastSeenAt
    offlineForMilliseconds[i] = offlineMilliseconds;
}

With higher order functions we use a function called map, and with it our solution becomes:

var offlineForMilliseconds = users.map(function(user) {
  return Date.now() - user.lastSeenAt
})

Hopefully you can see how much less complexity we’ve needed! It’s also more intention revealing – with the above, it’s unclear immediately whether offlineForMilliseconds will be longer or shorter than users: we know there’s a loop but we’ll have to read the whole thing to work out what type of operation it’s performing. In contrast, as soon as we read map we know we’re creating a list which has a new value for every item in the original.

If we use the new ES6 syntax (or Coffeescript), it’s even more obvious how much less work we’re having to do whether reading or writing the code:

var offlineForMilliseconds = users.map((user) => Date.now() - user.lastSeenAt)

Now when we need to make a new list from an existing one we immediately grab a map. As a result we’ve raised the abstraction of our program – our map code abstracts the generic mapping mechanism, and we supply the non-generic part of the procedure as a higher-order function.

Further reading

Higher-order functions don’t just apply to collections, they’re a universal way of abstracting away common tasks. Check out underscore.js to see how they’re used to for things like throttling how fast a function is called (great for keeping UIs snappy), or async.js where they help streamline complex asynchronous workflows.

Avoiding unnecessary variables

In OOP or procedural code we very often have shared variables, properties and data structures that are modified in the course of the program. To represent partial solved tasks we add items to arrays, change the value of local variables, or modify objects’ properties.

As in partition and map above, in FP code such modifications are hidden within a function’s local scope. As different parts of our program interact they do not share changeable variables or data-structures by default.

Why? Consider the example of dates in Javascript. If you think about a date in real life they’re very similar to numbers. If we ‘add’ a day to a date, we don’t ‘change’ the date, we simply start referring to a new date: just as 1 + 1 isn’t modifying one of the 1s into a 2. So it’s very strange that in Javascript we represent dates as an object that can change! Because it can change, we can create surprising bugs.

Let’s say we have a date, and we pass it to a reminder function to schedule a reminder:

var dateString = prompt("Please give me the date yyyy/mm/dd");
var date = new Date(Date.parse(dateString));
setupReminder(date,4);
saveEvent(event,date);

function setupReminder(date,hoursBefore) {
  date.setHours(date.getHours() - hoursBefore);
  saveReminder(date);
}

When would the event be scheduled? It’d be scheduled at 4 hours before we expect, because the Date object was modified within setupReminder! Javascript’s Date object is changeable unnecessarily – it’d have been far better to make the Date object behave like other values such as numbers, where addition returned a new date rather than modified the current one.

Objects were originally intended to model things with an identity that can change – but end up being used to model values that have no meaningful identity (you’d never ask ‘which Christmas Day 2013?’) and can cause bugs and unwanted complexity.

Sharing changeable data can cause problems because we can never be sure if code elsewhere in our program will change it later. Think of the number of times you’ve wanted to clone or copy an object to avoid this issue. Avoiding changeable data or shared variables allows us to avoid a whole type of potential bugs in our programs.

FP obviously can’t completely eliminate changeable data if it’s an essential part of a given problem. It simply suggests we separate the parts of our programs that manage state, and attempt to keep it only to essential pieces of state. So our Dates would become unchanging ‘values’ rather than changeable objects, as would a large number of the concepts often modeled with objects in OOP. Equally, unless there’s a performance limitation, we use unchangeable data-structures.

A place for objects

‘Object’, like many words in programming, has many meanings. Though it might seem like FP JavaScript wholly avoids objects we still use them, in three senses.

First we use objects as key-value data-structures: aka dictionaries, hashes or associative arrays. This has nothing to do with message passing: associating keys and values is an essential task, and all FP languages will have key-value data-structures.

Second we use objects to create modules. Rather than having all our functions in a flat global namespace we separate them as properties of key-value structures to organise related functions. Again, nothing to do with the idea of message passing, we’re just creating a module system in a language with no native one.

Third we use objects for the parts of a program that require interchangeable APIs around stateful processes or resources. Promises are a great example. Promises are a standard for representing the result of a process, and ideally you can write code that accepts and uses promises without knowing which of the many implementations it uses.

In other languages that are designed from the ground up to be more fully functional, concepts like promises can be expressed without objects. Practicality reasons mean it’s unwise to follow their lead when writing FP JavaScript – it’ll lead to slow, confusing and likely ugly code.

Structuring functional programs

How can we structure our program without objects? It depends on which type of program you’re writing.

For GUIs, objects map extremely well onto the problem – this was one of the primary areas of inspiration for OOP. If we look at the definition of OOP from Alan Kay, the inventor of the phrase “object-oriented”, we find that objects should be like biological cells: communicating by messages alone, the interpretation of which are left up to the receiving cell.

GUIs

So in GUI programming I personally often use objects to wrap the code of each widget. However the code inside those objects is functional. Whenever I’m interpreting data from APIs, formatting values for views or creating utilities to throttle input, I write functional code. This is a common pattern that – both Michael Feathers and Gary Bernhardt have independently identified ‘objects with a functional core’ as a great way of using the two paradigms together.

Implicit objects

The phrase ‘objects with a functional core’ might not mean what you think it does. It doesn’t require using ‘objects’ in a “classes, instances and constructors” sense at all. An ‘object’ is a role in Alan Kay’s definition – it’s something that accepts messages from the outside world. We don’t actually need our objects to be separate types of entities within JS or other languages: they could be separate processes! This is a common pattern for Node.js projects: very functional code inside the process that responds to events (messages) coming from outside. So two processes that communicate via a message queue are clearly fulfilling Alan Kay’s definition of objects. So too, on the front-end, are two systems of functions connected only by some kind of event emitter.

Next steps

If this overview has whetted your appetite here are some great next steps:

Use function programming every day

FP can be simple and fun, offering great abstraction power with less complexity from object systems or changeable shared data. It’s different, but at core it’s just a new way of using extremely familiar tools. I hope it helps you build cool things in 2014!