Skip to content

Instantly share code, notes, and snippets.

@jfhector
Last active March 5, 2022 14:15
Show Gist options
  • Save jfhector/6fdef9ac0cf281e30327f130796e6220 to your computer and use it in GitHub Desktop.
Save jfhector/6fdef9ac0cf281e30327f130796e6220 to your computer and use it in GitHub Desktop.
Lenses in JS

Lenses in JS

From "Mastering JavaScript Functional Programming"

/**
* These are not lenses
*/
const getField = attr => obj => obj[attr];
const setField = attr => val => obj => ({ ...obj, [attr]: val });
// ----------------------------
/**
* A lens is an object with a `getter` and a `setter` method.
* - Getter takes an object, and returns the value of one of the object's properties
* - Setter takes a value and an object, and sets that value on one the object's properties
*/
const createLensFromGetterAndSetter = (getter, setter) => ({ getter, setter });
const createLensFromPropertyName = attr => createLensFromGetterAndSetter(getField(attr), setField(attr));
/**
* 1st of the 3 basic functions to use lenses with
*/
const view = lens => obj => lens.getter(obj);
/**
* 2nd of the 3 basic functions to use lenses with
*/
const set = lens => value => obj => lens.setter(value)(obj);
/**
* 3rd of the 3 basic functions to use lenses with
*/
const over = lens => mappingFn => obj => {
const newValue = mappingFn(view(lens)(obj))
return lens.setter(newValue)(obj);
};
// ----------------------------
const myObj = {
name: 'JF',
bird: 'wood pigeon'
};
const nameLens = createLensFromPropertyName('name');
const viewName = view(nameLens);
const setName = set(nameLens);
const overName = over(nameLens);
console.log(
// viewName(myObj) // JF
// view(nameLens)(myObj) // JF
// setName('Hiro')(myObj) // { name: 'Hiro', bird: 'wood pigeon' }
// set(nameLens)('Hiro')(myObj) // { name: 'Hiro', bird: 'wood pigeon' }
// overName(x => x + x)(myObj) // { name: 'JFJF', bird: 'wood pigeon' }
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment