7 Ramda recipes

Useful function combinations

When working on a new project where I use Ramda I find myself creating a bunch of simple function which helps me better express my intent. Usually, those functions are a just simple combination of two or three of basic blocks provided in Ramda. Below is my top 7.

contained

Ramada provides useful function contains which abstracts common JavaScript pattern of haystack.indexOf(needle) !== -1. I find myself that I often need to switch the arguments order. That way I can build a function checking if given item belongs to a set of valid set of values.

Code

const contained = flip(contains);

Example

const validResponse = contained(['success', 'failure']);

if (validResponse(response)) {
  // ...
}

filterT

Ramda’s filter function expects two arguments. First, one is predicate and second a list of values. I find myself often checking if the list contains only truthful values, which can be simplified by creating function I call filterT (filter all Truth values).

Code

const filterT = filter(identity);

Example

if (filterT([true, 1, false, '']).length > 0) {
  // ...
}

allT

Similarly, to filterT there’s often the need to check if an array contains only truth values.

Code

const allT = all(identity);

Example

if (allT([1, 0, 1])) {
  // ...
}

safeHead

By default head is looking to get the first element of an array. The problem comes when the thing being checked for is not an array (most often an undefined returned when the property is missing). It would be nice if the code would not fail because of that.

My safeHead differs greatly from what would be a canonical implementation in Haskell, where the return value would be of type Maybe. It is possible to use that type in JavaScript but it is bit more complicated than what I usually need to do.

Code

const safeHead = compose(head, defaultTo([]));

Example

const obj = {foo: [1, 2, 3]};
const h = safeHead(obj.bar);

toTitle

Ramda contains toUpper and toLower which reflect JavaScript String’s object methods. Unfortunately, by default, there’s no way to the uppercase first letter of a string.

The code is not really converting whole string to title case, rather than just the first word. So far I found it useful enough.

Code

const toTitle = compose(
  join(''),
  over(lensIndex(0), toUpper)
);

Example

console.log(toTitle('test')); // => "Test"

imap

One difference between using Ramda’s map and built in Array’s map is the lack of access to the element index. In most cases it’s not a problem. So far my most frequent use case was with React.js and creating a list of nodes. Each one of those nodes requires unique key and array index usually is a perfect solution. With imap it still can be used.

Code

const imap = addIndex(map);

Example

<ul>
  {imap((el, i) => <li key={i}>{el.text}</li>, elements)}
</ul>

peek

Especially useful when debugging is an ability to inspect the value in a series of function applications.

Code

const peek = tap(console.log);

Example

// ...
const process = compose(
  save,
  peek,
  transform,
  retrieve
);
// ...
process('12');