A (mostly) Practical Guide to Functional Programming (in Javascript) Part 1

Posted on October 30, 2016

This the first follow-up post to a talk I recently gave at #HamOntJS. I started the talk by posing the question that has been bothering me for a while:

What can I say about functional programming that hasn’t already been said before?

The answer for me turned out to be simple: instead of repeating the same academic fundamentals let’s focus on real, practical examples where we can put functional programming to use. Let’s see if we can give people who already work with and manage a large code-base some patterns they can use to recognize where they could use functional programming techniques to improve their code.

In this follow-up post to that talk I want to dive in a little deeper and give some more examples as I go along.

Currying

Without going into too much detail, function currying is the technique of translating the evaluation of a function of arity N into a sequence of N functions of arity 1. It’s easier to visualize in code:

const myCurriedFunction = a => b => c => {
  return a + b + c
}

// is the ES6 syntax for curried functions... which translates to...

const myCurriedfunction = a => {
  return b => {
    return c => {
      return a + b + c
    }
  }
}

// and is roughly equivalent to

const myNonCurriedFunction = (a, b, c) => {
  return a + b + c
}

You might’ve already heard about curried functions before. You might have heard functional programmers explain it before and go on about function composition, monoids, and the like. They’re (usually) not wrong but I find such talk is immensely unhelpful if you’re wondering what this technique used for.

Well here’s a pattern I’ve seen in code for many years from all kinds of programmers:

function sendRegistrationEmail(emailTo, emailFrom, subject, username, link) {
  const email = `
      To: ${emailTo}
      From: ${emailFrom}
      Subject: ${subject}
      ---

      Hello ${username}! Thanks for registering with our service.

      Complete your registration here: ${link}`

  sendEmail(email)
}

Programmers new and experienced alike have handed me code similar to this to review. If they were hasty and didn’t write any unit tests I tend to ask them to do that before we start a review. And occasionally someone will come back and tell me they are struggling to get the unit tests to work.

Their difficulty usually lies in the fact that they have to find some way to create a test double for the sendEmail function. Those of us who are more experienced with this way of writing programs might have figured out mocks and spies… and have learned to live with it.

It doesn’t have to be this way. When someone is having trouble testing code like this I will ask them what would be different about the code if instead of looking up the definition of sendEmail in an outer scope we pass in the definition to the function. After all, Javascript is a language where you can pass functions as values… even to parameters.

Their eyes might widen a little when it hits them. “I could pass in my test double as a parameter and the real function in the code!”. They come back with a small change like this:

function sendRegistrationEmail(emailTo, emailFrom, subject, username, link, sendEmail) {
  // ... email template stuff here as usual

  sendEmail(email)
}

This is an improvement. Their tests are now much easier to orchestrate but their code is still difficult to work with. At every call to sendRegistrationEmail there needs to be a reference to the sendEmail function in scope to give to the appropriate parameter. And to make matters worse I add the requirement that this function needs to have different behaviours that depend on the execution environment. When we’re running in the development environment just log the emails to a stream. In our staging environment configure it to send emails only to the internal mail server. And of course in production we want to be able to configure the function to send emails to our current email provider (and yes we may need to change providers when the prices fluctuate).

At this point my inexperienced colleagues might be getting a little annoyed. I show them one more trick:

const sendRegistrationEmail => sender => (emailTo, emailFrom, subject, username, link) {
  // ... email template stuff here as usual

  sender(email)
}

What happened here?

Let’s take a moment to step back into Object Oriented Programming land and revisit the classic book by Bertrand Meyer, Object Oriented Software Construction. You may have heard about the open-close principle. To paraphrase, the principle states that:

A function should be open to extension yet closed to modification.

This means that users of your functions should be able to extend them with new behaviours without having to modify the source code to the function. Note that I said, “behaviours.” This is the pattern you should look out for in your code. They’re what functional programmers like to call, side effects.

It may sound like functional programmers despise side-effects. In reality we like side-effects! The difference is that functional programmers want to control when and where those side-effects happen in our code.

Now recall our curried sendRegistrationEmail function. When we call it with one argument, the sendEmail function, notice how it doesn’t immediately invoke it. We just get a new function back — the original, pure function we wanted to have in the first place. It can send your registration emails as before but now callers of your function can replace sender with any function which takes a string and does something with it. The nice thing about waiting to call it later is that we can compose the function we need by giving our curried function the behaviours we require and then call the new function later.

The pattern you want to look out for are functions where you call another function for its side-effect. Lift that side-effct up into a curried parameter. Now users of your function can extend it with any behaviour they need and they don’t have to file a pull-request against your code to do so. This works best with functions that have fewer than a handful of behaviours so keep your functions small.

And now that my novice programmer has tried the curried version of sendRegistrationEmail they’re happy because it’s easier to test, the module can configure the apporpriate function to the environment, and they don’t have to change the call sites where their function is being called. Their code is more beautiful, it’s easier to modify, and it’s extensible.

Isn’t programming beautiful?

For those of you coming from languages where function currying is the norm beware! If you have a curied function of arity N, Javascript won’t know what to do with the arguments if you pass them in one call. It will only pass the first argument. Again this is easier to see in code:

const foo = a => b => c => {
  console.log(`${a}, ${b}, ${c}`)
}

// cool, but...

foo(1, 2, 3)
// -> [Function]

// You have to supply each argument manually

foo(1)(2)(3)

If you want a more comfortable experience using curried functions then I suggest using a library called, Ramda.js. It has support for working with curried functions and more.

Conclusion

Currying is a useful technique for composing functions together. One practical application for that is lifting our side-effect calls into curried parameters so that users of our functions can extend them with new behaviours as they see fit. This pattern will make your code easier to test, more beautiful, and open to extension.

In my next post I will cover the topic of burri— ahem — Monads and give some practical examples of how you can use them today in your code to make it more beautiful, easier to maintain and extend, and all of those good things.

Addendum

In the original version of this post I incorrectly attributed the open-closed principle to the Gang of Four authors. This was an honest oversight on my part and I have since corrected the article.