Ramdajs - Functional Programming for Javascript

April 24, 2016

Warning: this post is written with my poor english

What is Ramda?

In short, Ramda is a utility library like underscore and lodash.

The different thing is that it strictly follows the Functional Programming (FP) style in its philosophy. Therefore, by using it you will be introduced to style of FP which, IMHP, will change the way you program and think when you program.

Should I learn to use and use Ramda?

Speaking for myself, the answer is definitely yes, because:

And for you, I do not know. But I do advise you give it a try, it is always good to exposed to new idea.

Ramda core features

Immutability

In functional programming, mutable state is considered extremely dangerous, marking programs hard to reason about, difficult to debug, and almost impossible to grow correctly into large, consistent systems. Ramda helps avoid this by refusing to ever mutate input data.

Avoiding side effects

By preventing mutating input data, Ramda also helps to avoid side effects. By not mutating input data, your function will be pure. Other functions use the same input with your function get what they expect.

Composing functions

Ramda encourges to write pure, re-useable, small functions. Then compose those functions to work on your data. This will make the code cleaner, debug-able, re-useable, maintainable.

Currying everywhere

As describe in this talk Hey Underscore, You’re Doing It Wrong!, data should come last in the arguments list to make function more reusable. Ramda requires data to be the last arg in the function signature so that it is easier to make function curried automatically. With Ramda it is guaranteed that all functions and returned function are curried automatically.

For me this is a stunning feature, it allows us to maximize the reusability of function. In the nutshell, let say before you pass in your data and get the result, everything are reusable.

Let’s try some examples

This is our data:

const studentList = [{
  name: 'dOg',
  nickname: ' goofY  ',
  score: {
    js: 7,
    html: 8,
    css: 9,
  },
}, {
  name: '  caT  ',
  nickname: 'tom',
  score: {
    js: 6,
    html: 7,
    css: 8,
  },
}, {
  name: 'MOUSE',
  nickname: '  jerry',
  score: {
    js: 8,
    html: 9,
    css: 10,
  },
}];

And there are three requirements:

  1. Tell me who are your students
  2. Tell me their js score
  3. Tell me their gpa

Tell me who are your students

const getName = R.prop('name');

const getListName = R.map(getName);

getListName(studentList); // -> ['dOg', '  caT  ', 'MOUSE']

Try in Ramda REPL

Ok, I have their names now, but can you do a little format stuffs? (trim, normalize)

const getName = R.prop('name');

const headToUpper = R.map(R.join(''), R.adjust(R.toUpper, 0));
// headToUpper('dOg') -> Dog

const normalizeStr = R.curry(R.composeK(
  headToUpper,
  R.toLower,
  R.trim,
  R.__
));

const getListName = normalizeStr(getName);

getListName(studentList); // -> ['Dog', 'Cat', 'Mouse']

Try in Ramda REPL

Good, what about their nicknames??

const getNickname = R.prop('nickname');

const getListNickname = normalizeStr(getNickname);

getListNickname(studentList); // -> ['Goofy', 'Tom', 'Jerry']

Try in Ramda REPL

Tell me their js score

const getScore = R.prop('score');

const getJs = R.prop('js');

const getJsScore = R.composeK(getJs, getScore);

getJsScore(studentList); // -> [7, 6, 8]

Try in Ramda REPL

Oh, looks good. But I do not know who each scores belongs to.

const jsScoreDetail = R.converge(R.zipObj, [getListName, getJsScore]);

jsScoreDetail(studentList); // -> {"Cat": 6, "Dog": 7, "Mouse": 8}

Try in Ramda REPL

Tell me their GPA

const getGPA = R.composeK(
  R.map(R.mean, R.values),
  getScore,
);

const getStudentGPA = R.converge(R.zipObj, [getListName, getGPA]);

getStudentGPA(studentList); // -> {"Cat": 7, "Dog": 8, "Mouse": 9}

Try in Ramda REPL

Conclusion

I hope the above examples bring you a feel of Ramda. I try to make them clear and easy to reason about, but still the best way is to try and understand yourself how good this library is.

Some may try to compare Ramda to underscore/lodash and debate about them. For me, I think that is useless because they are all good libraries and help you to get job done. The different is that Ramda introduces and teach you to how the real FP works, that is why I really like and want to use it.

I believe library come and go but their ideas will last, so I strongly encourage you give it try.