Ramda Thinking: Lenses

1. First steps
2. We combine functions
3. Partial application (currying)
4. Declarative programming
5. Ruleless Notation
6. Immutability and objects
7. Immutability and arrays
8. Lenses
9. Conclusion


This post is the eighth part of a series of articles on functional programming called "Thinking in the Ramda Style".


In the sixth and seventh parts, we studied how to read, update and transform the properties of objects and elements of arrays in a declarative and immutable style.


Ramda also provides a more general tool for performing these operations, called lenses.


What kind of lenses?


The lens combines the getter function and the setter function into one mechanism. Ramda provides a set of functions for working with lenses.


We can think of lenses as something that focuses on a specific part of a large data structure.


How can I create a lens?


The main way to create a lens in Ramda is the lens function. lens takes a getter function and a setter function and returns a new lens.


 const person = { name: 'Randy', socialMedia: { github: 'randycoulman', twitter: '@randycoulman' } } const nameLens = lens(prop('name'), assoc('name')) const twitterLens = lens( path(['socialMedia', 'twitter']), assocPath(['socialMedia', 'twitter']) ) 

Here we use the prop and path methods as our assocPath functions, and also assoc and assocPath as our setters functions.


Please note that we have duplicated the arguments with the name of the property and the path to the desired property for these functions. Fortunately, Ramda provides cool cuts for the most common lens usage situations: lensProp , lensPath and lensIndex .



We can rewrite our above-created lenses using lensProp and lensPath :


 const nameLens = lensProp('name') const twitterLens = lensPath(['socialMedia', 'twitter']) 

It is much easier and eliminates duplicates. In practice, I found that I almost never needed the original lens function.


What can I do with all this?


Okay, great, we created a pair of lenses. What can we do with them now?


Ramda provides three functions for working with lenses.



 view(nameLens, person) // => 'Randy' set(twitterLens, '@randy', person) // => { // name: 'Randy', // socialMedia: { // github: 'randycoulman', // twitter: '@randy' // } // } over(nameLens, toUpper, person) // => { // name: 'RANDY', // socialMedia: { // github: 'randycoulman', // twitter: '@randycoulman' // } // } 

Notice that set and over return the entire object with the modified value that your lens was focused on.


Conclusion


Lenses can be useful if we have a certain complex data structure from which we wish to abstract when calling a code. Instead of providing structure or providing getters, setters, and transformers for each available property, we can instead provide lenses.


Client code can then work with our data structures through the use of view , set and over without linking to the exact form of the data structure.


Further


Now we know about Ramda a lot of everything that it provides; in general, it is enough to do the majority of all the operations that we perform in our programs. The final article in this series reviews the subject and mentions some other topics that we may wish to explore on our own.

Source: https://habr.com/ru/post/415035/


All Articles