Ever Heard of Lenses?
Lenses are used in functional programming, and you’re probably using them without noticing!
Definition
As per the metaphor, a lens allows us to focus on a specific part (U
) of a larger object (V
):
Use case, please!
Lenses are especially useful when updating a subpart of an object in a context of immutability.
In the following example, we’re willing to update only the speed
of a car
. Writing car.speed = { value: 60, unit: "km/h" };
would not work because car
, the reference to the Car
object in memory, is unchanged. In doing so, we have shortcut the change detection mechanism (if working with Redux, for instance).
A Lens<Car, Speed>
allows to handle and update the speed
only, while returning a whole new car
object:
Lenses compose easily!
One can pipe lenses in order to build a “stronger” lens:
In the previous example, we focused on speed
. But now, within the Speed
object, we want to focus on its value, assuming the unit remains unchanged. Thus we create a second lens and combine both lenses:
Car --(focusOnSpeed)--> Speed --(focusOnValue)--> number
Car --(focusOnSpeedValue)--> number
Things get even more interesting with reducers!
Reducers are widely used in functional programming as a way to update a State
in an immutable fashion. In other words, they allow to compute an updated state without proceeding to the final mutation (state = updatedState
).
It appears that lenses compose very well with reducers:
How is that useful? Again, in the example below, it allows us to write a reducer for the sole speed
property of a car
and still get a whole brand new Car
object in the end:
Does this ring a bell?
Redux combineReducers
, yes!
See what the official Redux documentation says:
As your app grows more complex, you’ll want to split your reducing function into separate functions, each managing independent parts of the state. The
combineReducers
helper function turns an object whose values are different reducing functions into a single reducing function you can pass tocreateStore
.
Let’s be curious and have a glance at the code behind combineReducers
(starting at line 181, from Redux’ repository on GitHub):
See? That’s exactly what we would do with a lens, though the abstraction doesn’t surface here.
And that’s it! Lenses are one of the basic tools of functional programming. I would be happy to hear back from you, because I guess you’ll discover plenty of use cases!
Further readings
More content at plainenglish.io