6 Powerful Ramda Functions For JavaScript | by Tate Galbraith | Apr, 2022

A fast and functional library for supercharging your code

Photo by Markus Spiske on Unsplash

If you haven’t heard of the Ramda library for JavaScript, then you’re missing out on a beautiful enhancement to the language. This library is crammed with a ton of useful functions and utilities that not only solve common problems, but make JavaScript better at functional programming.

Ramda was developed as a functional library and provides concise, elegant but most importantly functional utilities. This means that many of the included functions have little to no side-effects, are curried and provide a flexible pipeline interface. With Ramda you can finally realize functional programming principles in JavaScript.

In this article, we’ll explore a few of my favorite functions provided by the library and show examples of how they can make your code more functional and less repetitive. Let’s get started.

Source.

If there is one task that comes up all the time in JavaScript it is “digging” into nested objects. Think about how many times you’ve had to grab a value from a deeply nested object. How many times has that object mutated slightly or had a missing key? Should you really have to manually check for the existence of every single intermediate key in the chain?

That sounds tedious.

Use the pathOr function from Ramda instead. This single function can replace a handful of spaghetti code. Check it out:

const R = require('ramda');let myObject = {
key1: {
key2: {
key3: { targetKey: 1234 }
}
}
}
let path = ['key1', 'key2', 'key3', 'targetKey'];
let result = R.pathOr(0, path, myObject);
console.log(result);

Let’s break down what is happening here:

  • First, we setup a simple nested object with some data. Our goal is to pull out the targetKey value.
  • Next, we setup an array that contains the ordered key names we’ll dig into.
  • Finally, we apply the pathOr function, passing a default value, the path and the object to key into.

If targetKey was not present or one of the intermediate keys was missing then pathOr would return the first default argument, which is 0.

The next time you need to dig into a nested object safely, just use pathOr.

Source.

This is a brutally simple function, but so handy to have. The clamp function ensures that a number falls within a particular range. This means that if you pass a number that is too high or too low the function will “clamp” that number to the closest acceptable number in the range you provide.

Here is a simple example:

const R = require('ramda');let result = R.clamp(10, 20, 5);console.log(result);

In this example we are clamping our range between 10 and 20. When we pass in 5, this is below the bottom-end of the range so it clamps to 10 instead. If we were to pass in anything above 20 it would clamp to 20.

You can also curry clamp into its own custom validation function like this:

let clampBetweenRange = R.clamp(10, 20);let result = clampBetweenRange(5);console.log(result)

There are a ton of applications for this particular function. You could clamp user input to a specific range or use this to guard against messy data outputs from other processing pipelines.

Source.

How many times have you been burned by a wild undefined or a null? How many times have you had to go back and build some elaborate try/catch statement for a seemingly simple feature?

Using the defaultTo function you can avoid some of these headaches.

The defaultTo function will accept a default value as the first argument and anything as the second. If the second argument is null, undefinedor NaN then the first argument gets returned. This can also be curried into its own wrapper function for much more readable, concise code:

const R = require('ramda');let resultNotCurried = R.defaultTo('error', undefined);console.log(resultNotCurried);let defaulted = R.defaultTo('error');
let resultCurried = defaulted(undefined);
console.log(resultCurried);

Now all you have to do to protect against bad values ​​is wrap your function or data in the curried defaulted function.

Source.

Although this is very similar to the built-in hasOwnProperty function of JavaScript, there is one key difference. You can curry this function and make it more elegant (and obviously, functional).

const R = require('ramda');let hasAge = R.has('age');let myObject = { name: 'Bob', age: 24 }console.log(hasAge(myObject));

Simply passing a key name to has will prepare the curried function. Now all you have to do to check for the presence of the key is wrap objects in the new function. Convenience at its finest.

You could even combine this with the previous defaultTo function using a Ramda pipe. This would create a robust data validation pipeline that can easily be reused. Check out the next section for an example.

Source.

Have you ever wished you could tap into the middle of a pipeline to see whats going on at a particular stage? With the tap function you can do just that.

When you have a ton of functions chained together, it can get confusing as to the state of some data in the middle of it. By leveraging tap You can log some output or save the data somewhere else for review.

Here is an example of “tapping” into the middle of a pipeline with Ramda:

const R = require('ramda');let logOutput = val => console.log(val);let pipeline = R.pipe(
R.inc,
R.tap(logOutput),
R.inc,
R.inc
);
let result = pipeline(100);console.log(result);

Here’s a breakdown of the steps:

  • First, we setup a function to log our output to the console. This is a simple function that accepts a value and logs it.
  • Next we build our pipeline. This is a simple Ramda pipe that will gradually increment a number. In reality, this would probably be a much more complex pipeline that manipulates data, but for this example we’ll keep it simple.
  • In the middle of our pipeline we stick our tap function and pass our logging function into it.
  • Lastly, we call our pipeline and provide it with a value.

If you were to run the example above, you would see two values ​​logged to the console: 101 and 103.

Using tap With pipelines we can easily investigate what is going on between steps and reduce the overall effort it takes to inspect complex function chains.

Source.

This function is one that is deceptively simple at first glance. A common theme in JavaScript is working with lists of objects. Whether this is data coming back from a database or some static JSON objects, manipulating these models is an all too frequent task.

The pluck function allows you to manipulate these lists of objects by “plucking” data out of each one. You can generate a new list of values ​​from a list of objects by specifying the key you want to “pluck” from each object.

const R = require('ramda');let myObjects = [
{ name: 'Bob', age: 22 },
{ name: 'Sally', age: 32 }
];
let results = R.pluck('name', myObjects);console.log(results);

By specifying the key to pluck and passing in the list of objects you’re able to build a new list containing only those keys.

The best part is that the pluck function also works against different types of structures as well. You can plug from list of lists and regular objects just as easily.

The world of functional programming can be incredibly vast and complex. The Ramda library provides a clear and simple way to bring this world into JavaScript without overwhelming developers.

Even if you’re not drinking the functional Kool-Aid programming yet, there are still a whole lot of useful functions in this library for more traditional development styles.

For a deeper dive into both Ramda and the basic principles of functional programming, check out Ramda your JavaScript by Marius Ibsen.

Leave a Comment