In functional programming, the Lenses pattern offers a solution for handling data manipulation in an immutable way. A Lens essentially serves as a first-class reference to a subpart of some data type. Despite its regular use in languages with built-in support for lenses (e.g. Haskell), a JavaScript developer can still incorporate the lens pattern via libraries or custom implementations.
This blog post will explore the lenses pattern and demonstrate how you can implement it in JavaScript to work with deeply nested paths.
What is a Lens?
A Lens is a functional pattern used to manage immutable data operations. They let us “zoom in”, or focus, on a particular part of a data structure (like an object or an array). Every lens consists of two functions: a getter and a setter.
Getter Function: Retrieves a sub-part of the data.
Setter Function: Updates a sub-part of the data in an immutable way.
An important feature of lenses is that they compose, meaning lenses focusing on nested data can be effectively chained to manipulate a required piece of data.
Implementing Lenses in JavaScript
Even though JavaScript doesn’t provide built-in support for lenses, we can create a custom lens function to achieve similar functionality. A basic lens function involves creating a getter and setter to retrieve and update the data respectively.
Let’s start simple and create a lens that is not dynamic, meaning it works with a single predetermined path:
function lens(getter, setter) { return { get: getter, set: setter }; }
But the real power of lenses comes when we make them handle deeply nested paths. To achieve that, we make our lens function accept a path (an array of keys), and modify our getter and setter to navigate the object using this path:
function lens(path) { return { get: (object) => path.reduce((obj, key) => obj && obj[key], object), set: (value, object) => { const setObjectAtKeyPath = (obj, path, value) => { if (path.length === 1) { return { ...obj, [path[0]]: value }; } const key = path[0]; return { ...obj, [key]: setObjectAtKeyPath(obj[key] || {}, path.slice(1), value) }; }; return setObjectAtKeyPath(object, path, value); }, }; }
To use this lens, we create a path array indicating the sequence of keys to the desired property, and pass this path to the lens function. The returned lens object provides get and set methods for reading and updating the property:
const person = { name: "John Doe", address: { street: "123 Main St", city: "Any town", country: "USA" }, };
// Create a lens for the address.street path: const streetLens = lens(["address", "street"]);
// Get street using the lens: console.log(streetLens.get(person)); // Outputs: 123 Main St
// Set street using the lens, resulting in a new (immutable) object: const newPerson = streetLens.set("456 Broadway St", person); console.log(newPerson); // Outputs the new person object with the updated street
Conclusion
The lenses pattern rewards developers with the ability to maintain immutability while easily accessing and updating deeply nested data structures. The effectiveness and elegance of lenses are in their composability and the simplicity of resulting code. While JavaScript does not support lenses natively, we’ve seen how to produce a lens like behaviour using array methods and recursion. However, for simplification, this custom implementation does not handle edge cases that established libraries do. Thus, for production-level code, consider using libraries such as Ramda or partial.lenses that offer more comprehensive lens functionalities.
Link to my original article:
https://dev.to/ashutosh_mathur/understanding-and-implementing-the-lenses-pattern-in-javascript-333a
#Javascript #functional-architecture-pattern #frontend #ramda
20 Comments
Your article helped me a lot, is there any more related content? Thanks!
Thank you ever so for you article.Really looking forward to read more. Want more.
Thanks , I’ve recently been searching for information about this topic for ages and yours is the greatest I’ve discovered till now. But, what about the conclusion? Are you sure about the source?
lasix india I JOURNAL everything I eat and keep track of my calories
Really a lot of very good data.graphic organizers for writing essays write my essay professional personal statement writing services
Your people are more likely to respond to offers made via mobile messages. The old standbys have to be fed, but they won’t fuel a growth rebound. However it’s not actually free – you shell outside in decreased security.
Hi there, just became alert to your blog through Google, and found that it’s really informative.I’m going to watch out for brussels. I’ll appreciate if you continue this in future.Lots of people will be benefited from your writing.Cheers!
My brother recommended I might like this blog. He was totally right.This post actually made my day. You cann’t believesimply how much time I had spent for this info! Thanks!
It’s really a nice and useful piece of information. I am glad that you simply shared this useful info with us. Please stay us up to date like this. Thank you for sharing.
Thank you, I’ve just been looking for information about this subject for a long time and yours is the best I’ve discovered till now.But, what about the bottom line? Are you positive aboutthe supply?
I really like and appreciate your blog article.Much thanks again. Much obliged.
Fantastic blog article. Fantastic.
Very neat blog article.Really thank you! Really Cool.
Very neat article. Want more.
Hey, thanks for the blog post.Thanks Again. Keep writing.
Thanks again for the article post. Much obliged.
modalert online provigil side effects Loading…
Thanks-a-mundo for the blog.Really looking forward to read more. Want more.
I appreciate you sharing this post.Thanks Again. Really Cool.
Thanks again for the blog article.Really looking forward to read more. Cool.