Ever Heard of Lenses?

Lenses are used in functional programming, and you’re probably using them without noticing!

Mathieu Eveillard
JavaScript in Plain English

--

Two black camera lenses on giraffe painting photo.
Photo by James Bold on Unsplash

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!

Man holding black DSLR camera and a lens.
Photo by Jakob Owens on Unsplash

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 to createStore.

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

--

--