3 lessons I learned getting started with Ramda
Some lessons that I learned while adding Ramda to a project, to help with taking a more functional approach.

Ramda is all about those functional pipelines
I did a functional programming course once.
As much as I tried at the time, I couldn’t wrap my head around it. I’d struggle to write anything coherent in Haskell today, I still couldn’t tell you what a monad is, or explain the ins and outs of the other mathematical concepts related to functional programming.
With time, though, I have come to really appreciate the approach that functional programming paradigms encourage. The concepts often lead to code that is much easier to reason about, test, compose, and adapt over time.
I have a project that I’ve worked on for years. One of those, “I’ll finish it someday” projects. I often use it to try different approaches and libraries, as it has enough complexity to make it an interesting example and I’m not too concerned about when I finish it. Sometimes, as the saying goes, it’s about the journey more than the destination!
In this post, I’ll go through some lessons that I learned while adding Ramda to that project, to help with taking a more functional approach.
Ramda is a collection of functions that “makes it easy to create functional pipelines”. It’s pretty easy to get started with, but after a while, I did find myself learning a few lessons around how to get the most out of it.
If you’re looking for more of an explainer on functional programming, there’s plenty of other great articles for that. Here’s one example:
An Adequate Introduction to Functional Programming
This list of libraries and other resources is also worth looking at:
Leason 1 — Ramda function naming can be confusing
Ramda has a lot of functions, so if you need to do something, there’s probably a function for it.
However, I found it difficult to find what I was looking for because some of the namings seemed a bit non-obvious. For example, I found R.evolve useful in multiple cases for applying different transforms to each property in an object, but I only found it by chance.
Make sure to explore the docs, you’ll find some interesting tools!
Lesson 2 — Keep it simple
You’ve had a look through the docs and found some interesting methods. All of these methods are great for more complicated logic, but they can also make a relatively simple piece of logic much more difficult to understand.
Let’s take an example — say you want to take the first element from an array, and return that element if it is greater than 0, else return undefined. With Ramda, that could look something like:
R.ifElse(
R.pipe(R.nth(0), R.gt(R.__, 0)),
R.identity,
R.always(undefined)
);
On the other hand, an equivalent lambda function could look something like this:
([elem]) => elem > 0 ? elem : undefined;
While all the methods that Ramda offers can be useful, it’s pretty easy to end up staring at some code you’ve just written, trying to remember what on earth you were even trying to do.
Ramda is there to help write code in a functional way, not to be the only way to write functional code.
Lesson 3 — Need to pass variables through to a middle pipe stage? Use a lambda!
Once you start writing more complex pipelines, you’ll eventually reach a point where you have a stage that needs access to a parameter that’s passed in at the start of the pipeline.
We could modify the previous stages to pass through this parameter. However, we’ve now made them aware of knowledge that isn’t important to them (the new parameter) and tied them specifically to this pipeline.
We could instead wrap each method in an adapter:
const passThrough = (func) => ([arg1, arg2]) =>
([func(arg1), arg2]);
R.pipe(
(arg1, arg2) => ([arg1, arg2]),
passThrough(stage1),
passThrough(stage2),
stage3,
stage4);
This adapts the previous stages so that the needs of the later stage can be met, but without having to adjust the reusable stage itself.
A second alternative I found was just to wrap the pipeline in a lambda:
(arg1, arg2) => R.pipe(
stage1,
stage2,
stage3(arg2),
stage4,
)(arg1);
While this does work, it feels a bit hacky as it introduces top-level state. However, I did found it easier and quicker than the pass-through option above. Which approach makes sense will likely depend on the situation and your own (or your team’s) preferences.
These are as much for my reference as anything else, but I hope these lessons are useful to anyone else getting started with Ramda. If there’s anything you found useful when getting started with Ramda, or if you have questions/thoughts about the above, let me know!



