ramda’s functions can all be curried

Functions in ramda, a functional JavaScript library, can be curried.

To explain what I am talking about, I will use the assoc function available in ramda as an example.

Note: I created a jsbin you can play with to demonstrate the points I am making.

The assoc function is used to set or change properties on objects.

In the functional programming paradigm we avoid mutating values, so assoc returns a shallow cloned object with a property’s value changed. Here is an example:

const obj = {x: 'foo', y: 'lol'};

const newObj = R.assoc('x', 'bar', obj);
console.log(newObj); // logs `{x: 'bar', y: 'lol'};`

As you can see, the x property of obj was changed from 'foo' to 'bar' in the returned object.

obj remains unchanged:

console.log(obj); // logs `{x: 'foo', y: 'lol'};`

Now instead of passing in all arguments at once, you can pass in just the ones you want to curry, and the result is a function that you can call later to pass in the other arguments.

In the example that follows we do the exact same thing as before, but we are calling all the curried functions all at once:

const obj = {x: 'foo', y: 'lol'};

const newObj = R.assoc()('x')('bar')(obj);
console.log(newObj); // logs `{x: 'bar', y: 'lol'};`

Currying like this can be useful when you want an operation to always make the same transformation on an object.

Say we want a function that always changes the x property on an object.

We can use ramda’s built in currying to create a version of assoc that returns a function that when passsed an object returns a clone of the object with the property x changed.

const obj = {x: 'foo', y: 'lol'};

const assocX = R.assoc('x');

console.log(assocX('bar')(obj)); // logs `{x: 'bar', y: 'lol'};`
console.log(assocX('foobar')(obj)); // logs `{x: 'foobar', y: 'lol'};`

Notice that we did not have to specify the x property again. The property we chose to modify is curried into the assocX function. We can curry more parameters than just one: maybe we might want a transformation that always changes the value of an x property in an object to 'bar':

const obj = {x: 'foo', y: 'lol'};

const assocXBar = R.assoc('x', 'bar');
console.log(assocXBar(obj));  // logs `{x: 'bar', y: 'lol'};`

This is pretty neat. This ability to curry arguments is, as far as I can tell, shared by all of the many valuable functions you get from ramda.

If their value is not immediately obvious, consider that curried functions like this can be passed into map to iterate over an array of objects and return new objects. They can be composed with other functions to create powerful transformations in an expressive way. These functions could be used with other functional libraries, like rxjs. You could use them in rxjs to modify browser click events or web socket events. You could use them in cycle.js to transform xstream streams to change how a component is rendered.

Ramda is a great functional library and I have learned a lot about it by reading the thinking in ramda posts and watching ramda videos on egghead.io.


Now read this

Maps, Sets and Iterators in JavaScript

In my last JavaScript post I wrote about about how to make advanced usage of objects in JavaScript. Continuing in a similar direction, in this post I want look at some new kinds of objects in JavaScript. I will look at maps and sets,... Continue →

Subscribe to Bjorn Tipling

Don’t worry; we hate spam with a passion.
You can unsubscribe with one click.