Instantly share code, notes, and snippets.

Embed
What would you like to do?
JavaScript: Lenses (Functional Programming)
// FP Lenses
const lens = get => set => ({ get, set });
const view = lens => obj => lens.get(obj);
const set = lens => val => obj => lens.set(val)(obj);
const over = lens => fn => obj => set(lens)(fn(view(lens)(obj)))(obj);
const lensProp = key => lens(prop(key))(assoc(key));
// Generic FP utils
const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
const map = fn => list => list.map(fn);
const filter = fn => list => list.filter(fn);
const lt = left => right => left < right;
const add = left => right => left + right;
const upper = str => str.toUpperCase();
const prop = key => obj => obj[key];
const assoc = key => val => obj => { obj[key] = val; return obj; };
/**
* Example usage: Object
*/
const amountLens = lens(prop('amount'))(assoc('amount'));
over(amountLens)(add(5))({ x: 1, amount: 10 });
//=> { x: 1, amount: 15 }
/**
* Example usage: Array
*/
const headLens = lens(prop(0))(assoc(0));
over(headLens)(upper)(['first', 'second']);
//=> [ 'FIRST', 'second' ]
/**
* Example usage: Chaining
*/
const moneyLens = lensProp('money');
const data = [{ money: 42 }, { money: 1024 }, { money: 1337 }];
compose(
map(over(moneyLens)(add(''))),
filter(compose(lt(100), view(moneyLens)))
)(data);
//=> [ { money: '€ 1024' }, { money: '€ 1337' } ]
/**
* Example usage: Composition
*/
const article = { title: 'FP ftw!', comments: [{ t: 'boo!' }, { t: 'yay!' }] };
over(lensProp('comments'))(map(over(lensProp('t'))(upper)))(article);
//=> { title: 'FP ftw!', comments: [{ t: 'BOO!' }, { t: 'YAY!' }]}
@leihuang69

This comment has been minimized.

Show comment
Hide comment
@leihuang69

leihuang69 Aug 22, 2018

This implementation mutates the original data.

leihuang69 commented Aug 22, 2018

This implementation mutates the original data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment