An Intro to Functional Programming Concepts in JavaScript

Much of functional programming is about composing functions together to handle our data in predictable ways. Simple functions neatly tied together create increasingly complex, yet dependable functions to build upon.

This blog post is part 1 of a multi-part series. In part 1, we will introduce the library Ramda and the concepts of composition, pointfree style, and functors through the simplest of examples.

Disclaimer: Please note that I am not an authority on functional programming by any means. I intend this little series solely as “introduction to concepts”. This guide is quite unconventional in the order of the content. I choose to focus on practical examples, leaving out essential theory such as typeclasses and function purity. If you thirst for more technical resources, I highly recommend http://github.com/MostlyAdequate/mostly-adequate-guide, or you can also check out this free ebook on Haskell: http://learnyouahaskell.com/.

Let’s jump right in and explore some functional concepts in the land of JavaScript.

Getting Our Feet Wet

Let’s say we have a person in a string format such as: Doc Emmett Brown. Our task is to obtain the person’s first initial, so simply creating the string “E” in this very case.

If you are reading this, you might already be keen to program with small functions that have single responsibilities. Let’s build on top of this idea from scratch with this starter code:

getFirstInitial is the main function. In it actually lies the essence of compositional programming (the function is nested). We build on top of the first two simple functions (that are trivial to test and debug) to create a slightly more complex function that we can rest assure is fundamentally sound! Easy does it.

Yet, you might agree that our nested function here doesn’t look all that friendly (although ES6 makes it quite tolerable with the arrow syntax). It’s a bit of an eye sore and not too appealing to work with, given how simple the logic actually is:

return getFirstLetter(getFirstName(person))

It’s not incomprehensible by any means, but complexity is our enemy so let’s nip it in the bud.

Let’s Compose with Ramda

We can do better by composing our functions together. Let’s import Ramda’s pipe function and update our code:

Ramda’s pipe lets you nest functions together more intuitively than we did in standalone JavaScript. Whatever data is passed into firstInitial will first run through getFirstName, which will pass the result to getFirstLetter, which in turn gives us our final result!

The code is easier to grok and to maintain this way. We’re easily nesting or composing functions together. In fact, there is an equivalent function in Ramda called compose and it does the exact same thing as pipe, but the arguments go in the reverse direction, like so:

compose(getFirstLetter, getFirstName);

I prefer pipe and reading the code like normal English (left to right). Ramda does a lot more than composition (we’ll see more use cases in part 2).

PointFree Style

Something else interesting is happening here with pipe and compose. In our original getFirstInitial function, we had a reference to person in there (in fact we even had two), take a look:

With Ramda, the function definition is free of that pesky data reference. Isn’t it nicer on the eyes (and on the brain)? That’s called pointfree style.

You don’t have to tie your function to a “person” input variable (or rename that variable over time). It’s more encompassing this way: we could as well pass in a fictional character that fits the format of the string but isn’t necessarily a person (“Smurf Papa Smurf”).

More Syntax Goodness

Note how you could drop another function in the middle of this composition easily, let’s say a log function (if we had implemented one).

pipe(getFirstName, log, getFirstLetter)

Think about doing that with the original nested function. Couple times as long to edit? Here it is:

return getFirstLetter(log(getFirstName(person)));

It’s rather ugly. Wait, did I get the parentheses just right?

The Real World

Let’s say our original input string could very well be null. No data. What happens when we call firstInitial(null)? It breaks! It begins as instructed with getFirstName, goes in to try to perform String.split on what turns out to be null, and it errors out.

Alright, no biggie, we could sprinkle our app with null checks in our functions to avoid this unfortunate turn of events.

Now, when we try to get the firstInitial of a null, we get null back, which is fairly reasonable. More importantly, the app didn’t blow up on us.

But let’s say a new requirement later follows that dictates we also check for undefined as well as null! We have to go back and change all the instances of these null checks in the nitty-gritty of our building blocks. It would work but it’s not really ideal. We don’t wanna mess with our building blocks every couple of minutes.

Do it, But Maybe

How can we lift our invalid checks outside of each individual function, so we can deal with them in one place? The pattern is always the same as we see in the duplication of the code above: if the value is null, don’t do anything and just return null.

if(name===null) return null;

The key abstraction here lies in wrapping our data in a container that can perform its own check. Then, we pass around this container instead of passing around the raw data.

It’s a bit of leap, but bear with me. Let’s make such a container, why don’t we?

In JavaScript, we have objects, so let’s use that. A container (or wrapper) object will store our actual value, as well as a method that can look at that value and use it to return a new wrapped value!

We’ll call this container method fmap (for functor map)It’s reminiscent of Array.map in that it looks inside the data structure (the array or the container) and returns a new structure based on the original element(s).

We’ll create a container factory that produces these container objects for us. We’ll call our factory Maybe, because the wrapped value may or may not exist (may or may not be null).

Let’s see this container concept in code:

Our Maybe factory takes in a value and returns a new object with that value as val as well as a fmap method. fmap itself accepts a function f as a parameter, checks this.val and calculates a new value to wrap and return! It’s nice that it wraps it for us because then we can keep “fmapping” over it. Just like Array.map returns you an array and you can .map again.

If the ES6/2015 is unfamiliar, here is an ES5 implementation of Maybe:

Interesting, isn’t it? Maybe actually returns a functor, which is loosely described as any data structure that can be mapped over. And “mapped over” simply means you are creating (or “projecting”) a new value based on the original one (with a function).

Fixing the building blocks

Now, we need to change getFirstName and getFirstLetter to handle our Maybe containers instead of plain strings (which in fact could be null!) Let’s do some updating:

We’ve now delegated the null check to the Maybe container! The great thing is that Maybe is nice enough to provide its own interface (as we built it ourselves!) so it can act based on its own internals. It’s introspective. We just call its fmap method passing in a function that we want to invoke on the internal value… as long as it‘s not gonna crash the app!

Let us recap our code, including a check for undefined.

Feel free to fork and edit this code at: http://codepen.io/collardeau/pen/JYpLEY

Now we can compose with more ease and assurance thanks to our new functor Maybe.

Stay tuned for part 2, where we shall learn about currying. Fun stuff ahead.
Update: Part 2 is now available.

Feedback is always appreciated. You can also follow me on twitter.

Thanks for reading!