Recently I've been playing with the functional programming JavaScript library Ramda.js. I got interested in "real" functional programming after seeing Brian Lonsdorf's talk from React Rally 2016 and subsequently his Classroom coding with Prof. Frisby videos.

Initially, I didn't find this method of writing code very intuitive; I'm still finding it hard to solve problems in this functional mindset, so I've been putting together some videos on Ramda, where I try to explain my thought processes, in hopes of tricking myself into clarifying said processes.

If you're interested in seeing Ramda "in the wild," you might enjoy the videos.

However, if you haven't used Ramda before, those videos aren't the place to start. This article is the place to start.

What can you do with Ramda?

It wasn't that long ago that I thought functional programming was using Underscore or Lodash. If that's where you are, then you could start by replacing those libraries with Ramda. The function names are mostly the same, but it's not quite a drop in replacement: the array isn't the first parameter, but the last one. So, given some user data:

let users = [  
  { name: 'Jimmy', age: 56 },
  { name: 'Linn',  age: 32 },
  { name: 'April', age: 28 },
  { name: 'Adam',  age: 49 }
];

We could filter the array easily with both Underscore or Ramda:

const ageOver30 = user => user.age > 30;

_.filter(users, ageOver30);  
R.filter(ageOver30, users);  

Ramda has other Underscore functions you're probably familiar with, like map and property (Ramda calls it prop):

_.map(users, _.property('name'))  
R.map(R.prop('name'), users);

// Both return: ['Jimmy', 'Linn', 'April', 'Adam']

So, using Underscore, how would we create a function that takes an array and returns the name of the first person over 30?

 const nameFirstOver30 = (arr) =>
    _.property('name')(_.head(_.filter(arr, ageOver30)));

Not too hard: we filter the list, use head to get the first item in the list, and then pass it to the function that property returns.

This is the first place where Ramda begins to shine. First, based on what we know so far, here's how we might write this using Ramda:

 const nameFirstOver30 = (arr) =>
    R.prop('name')(R.head(R.filter(ageOver30, arr)));

But this could be much better.

A Side-dish with Curry

Let's focus on R.prop('name') for a second. What you can't tell by looking at it is that we're actually currying its second argument. We can actually use R.prop this way:

R.prop('name', { name: 'Jimmy' }); // 'Jimmy'  

However, all of Ramda's functions are curried, which means if we don't supply all the necessary parameters, instead of returning the appropriate value, it will return a function that takes the remaining parameters and then returns the value.

Here's a simpler example. R.add takes two numbers and adds them together:

R.add(1,2) // 3  

However, if we only pass a single parameter, we get a function instead: one that expects to receive the second parameter, and will return the value that we would have received if we passed both arguments at the same time:

const add42 = R.add(42);  
add42(8) // 50  

All Ramda's functions are curried, so you can give them as few arguments as you want and get a curried function in return.

So, what does this mean for our nameFirstOver30 function? Well, it means we could do this:

 const nameFirstOver30 = (arr) =>
    R.prop('name', (R.head(R.filter(ageOver30, arr))));

Not a big difference, you say. But an important one, I argue.

Composing a Masterpiece

Notice that these function calls are nested perfectly, like the dolls. This pattern is so common in functional programming that Ramda has a function that will perform this nesting for us. We can pass it as many functions as we'd like, and it will nest, or compose them. It's called R.compose. The function that is returned expects a parameter which is passed (like arr above) as the last parameter to the innermost function.

For example, passing two functions to R.compose would look like this:

const filterOver30 = R.filter(ageOver30);

const OnlyFirstOver30 = R.compose(R.head, filterOver30);  

Remember, this works because we're currying R.filter by not passing it a second argument (an array). The function we've created, OnlyFirstOver30, would be easy to write on our own:

const OnlyFirstOver30 = arr => R.head(filterOver30(arr));  

But I hope you'll agree that the R.compose syntax is nicer. There are other benefits, of course, that I'm not going into here, mainly because it's been done better elsewhere. I'm thinking particularly of Brian Lonsdorf's book Professor Frisby's Mostly Adequate Guide to Functional Programming, but there are other great resources as well.

So, to wrap it up, we wrote this function earlier:

 const nameFirstOver30 = (arr) =>
    R.prop('name', (R.head(R.filter(ageOver30, arr))));

Using R.compose, we can say, more succinctly:

 const nameFirstOver30 = R.compose(
    R.prop('name'),
    R.head,
    R.filter(ageOver30));

There's a lot more that you can do with Ramda; the Ramda REPL makes it easy to play around. If you've found this quick intro helpful, then you'll probably like the Ramda By Example video series I'm putting together.

Otherwise, you probably know more about this than I do. So let me know where I'm wrong.