This post is Part 7 of a series about functional programming called Thinking in Ramda.
In this post, we’ll do the same for arrays.
Reading Array Elements
In Part 6, we learned about various Ramda functions for reading object properties, including
has. Ramda has even more methods for reading array elements.
The array equivalent of
nth; the equivalent of
slice, and the equivalent of
contains. Let’s look at those.
Slice takes two indexes and returns the sub array starting at the first index (0-based) and including all of the elements up to, but not including the second index.
Accessing the first (
nth(0)) and last (
nth(-1)) elements is quite common, so Ramda provides shortcuts for those special cases,
last. It also provides functions for accessing all-but-the-first element (
tail), all-but-the-last element (
init), the first
N elements (
take(N)), and the last
N elements (
takeLast(N)). Let’s see these in action.
Adding, Updating, and Removing Array Elements
For objects, we learned about
omit for adding, updating, and removing properties.
Because arrays are an ordered data structure, there are several methods that do the same job as
assoc. The most general are
update, but Ramda also provides
prepend for the common case of adding elements at the beginning or end of the array.
prepend add new elements to the array;
update “replaces” an element with a new value.
As you might expect from a functional library, all of these functions return a new array with the desired changes; the original array is never changed.
For combining two objects into one, we learned about
merge. Ramda provides
concat for doing the same with arrays.
Note that the second array is appended to the first. This looks right when used by itself, but as with
merge, it may not do what you expect when used in a pipeline. I find it useful to define a helper function,
const concatAfter = flip(concat) for use in pipelines.
Ramda also provides several options for removing elements.
remove removes elements by index, while
without removes them by value. There’s also
dropLast for the common case of removing elements from the beginning or end of the array.
remove takes an index and a count whereas
slice takes two indexes. This inconsistency can be confusing if you’re not aware of it.
As with objects, we may want to
update an array element by applying a function to the original value.
To simplify this common use case, Ramda provides
adjust that works much like
evolve does for objects. Unlike
adjust only works for a single array element.
Note that the first two arguments to
adjust are swapped when compared with
update. This can be a source of confusion, but makes sense when you consider partial application. You might want to provide an adjustment function with
adjust(multiply(10)) and then later decide which index and array to apply that adjustment to.
We now have tools for working with arrays and objects in a declarative and immutable way. This allows us to build programs out of small, functional building blocks, combining functions to do what we need to do, all without mutating our data structures.
We’ve learned ways of reading, updating, and transforming object properties and array elements. Ramda provides a more general tool for performing these operations, the lens. Lenses shows us how they work.