Книга: Functional Programming in JavaScript
Назад: Promises
Дальше: jQuery is a monad

Lenses

Another reason why programmers really like monads is that they make writing libraries very easy. To explore this, let's extend our object with more functions for getting and setting values but, instead of using getters and setters, we'll use lenses.

Lenses are first-class getters and setters. They allow us to not just get and set variables, but also to run functions over it. But instead of mutating the data, they clone and return the new data modified by the function. They force data to be immutable, which is great for security and consistency as well for libraries. They're great for elegant code no matter what the application, so long as the performance-hit of introducing additional array copies is not a critical issue.

Before we write the function, let's look at how it works.

var first = lens(   function (a) { return arr(a)[0]; }, // get   function (a, b) { return [b].concat(arr(a).slice(1)); } // set ); first([1, 2, 3]); // outputs 1 first.set([1, 2, 3], 5); // outputs [5, 2, 3] function tenTimes(x) { return x * 10 } first.modify(tenTimes, [1,2,3]); // outputs [10,2,3]

And here's how the function works. It returns a function with get, set and mod defined. The function itself is a functor.

var lens = fuction(get, set) {   var f = function (a) {return get(a)};   f.get = function (a) {return get(a)};    f.set = set;   f.mod = function (f, a) {return set(a, f(get(a)))};   return f; };

Let's try an example. We'll extend our object from the previous example.

// userName :: User -> str var userName = lens(   function (u) {return u.getUsernameMaybe()}, // get   function (u, v) { // set     u.setUsername(v);       return u.getUsernameMaybe();    } );  var bob = new User(); bob.setUsername('Bob'); userName.get(bob); // returns 'Bob' userName.set(bob, 'Bobby'); //return 'Bobby' userName.get(bob); // returns 'Bobby' userName.mod(strToUpper, bob); // returns 'BOBBY' strToUpper.compose(userName.set)(bob, 'robert'); // returns 'ROBERT' userName.get(bob); // returns 'robert'
Назад: Promises
Дальше: jQuery is a monad

bsn
thank
Vesa Karvonen
I hope you don't mind, but I’d like to point you and your readers to my high-performance optics library for JavaScript that is in production use in multiple projects, has comprehensive support for partial optics and interactive documentation: https://calmm-js.github.io/partial.lenses/ (this takes a moment to load — be patient!)