const arr = [1, 2, 3]; const arr 2 = _.map(arr, (e) => e + 1);
Lodash was born three years after Underscore, in 2012. It's pretty interesting to know that it is a pull request from John-David Dalton on Underscore that allows the creation of Lodash. John-David Dalton insisted on the performance and the consistency between browsers to promote his library! Lodash actually provides the same set of functions but don't worry, they don't necessary have the same name or there may be some differences between them. For example the flatten function is shallow with lodash but it is deep with underscore. For example.
//Lodash _.flatten([[1, 2, ]]); //[1, 2, ] //Underscore _.flatten([[1, 2, ]]); //[1, 2, 3]
Did you notice that in both cases with lodash and underscore, I used
_.<function>. Don't forget that lodash was born from Underscore, so the lodash syntax is really close to the underscore one!
Lodash also provides some facilities with chaining, custom builds that Underscore doesn't! Another thing to note, is that the releases of Lodash are more frequent than the Underscore ones.
Ramda is by far the youngest one. It was first released at the end of 2013. The reason why I love Ramda so much is because it is the much functional one. Why? Because of CURRYING! In functional programming language, currying allows you to create a function from another function by not providing all arguments. So let's take an example (with Ramda):
const addOneToNumbers = R.map(x => x + 1);
In this example,
addOneToNumbers is a function that was created from the R.map function. Did you notice that I didn't provide all the arguments of the map function. I omitted to provide the collection on which the callback will interact on. So, by now I can use
addOneToNumbers with different collections:
const arr1 = [1, 2, 3]; const arr2 = [4, 5, 6]; addOneToNumbers(arr1); // [2, 3, 4] addOneToNumbers(arr2); // [5, 6, 7]
Ramda functions are automatically curried. So you can do what I did with all Ramda functions. Isn't that awesome?
From my experience, it is really useful when you need to manipulate structure like promises or observables. Let's take an example. Suppose we want to fetch all the avatars of the github users. With ramda, we can write something like:
$.getJSON('https://api.github.com/users?since=135') .then(R.pluck('avatar_url')) .then((d) => console.log(d));
With lodash, we would write something like:
$.getJSON('https://api.github.com/users?since=135') .then((users) => _.map(users, (user) => user.avatar_url)) .then((d) => console.log(d));
Notice how concise it is with Ramda. I didn't need to create a lamda function to just map over the users. It was pretty straightforward with the currying thing!
You can find the working example here
Ramda also respects the principle of mutability. It nevers mutates a variable. So for example, when you use the
R.merge(o1, o2) function, you have the certitude that o1 and o2 paramters had not been mutated. This is not the case with lodash or underscore. So you have to be really careful with Lodash or Underscore when you use a function. With Ramda, it is safe!
Lodash recently provided the lodash/fp, a module to promote a more functional programming style. This module allows you to use a curried version of the lodash functions. These functions are also safe in term of mutability. So you can use
mergeAll and other functions safely without caring about mutability! So if you're attached to lodash, I think it is a good alternative to Ramda
I hope I've convinced you to give a try to Ramda. I often had pain to impose Ramda in my teams. People are often too attached to Lodash and they use it, just because it seems cool, never caring about the how and why. So, if you don't really write a functional code, and just want to write with an imperative style, prefer using native ES6 functions like map, reduce or filter.There is an intersting repository here that takes the comparison between lodash functions and the native ones.