Skip to content

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 => Object.assign({}, obj, {[key]: val});
/**
* 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 assocArray = idx => val => arr => {
const clone = arr.slice();
clone[idx] = val;
return clone;
}
const headLens = lens(prop(0))(assocArray(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.

Copy link

commented Aug 22, 2018

This implementation mutates the original data.

@dimitris-papadimitriou-chr

This comment has been minimized.

Copy link

commented Jul 20, 2019

just put Object.assign({}, object, {[key]: value}) to copy the objects so the purists feel comfortable. That's the one page introduction for a senior developer .Thanks

@branneman

This comment has been minimized.

Copy link
Owner Author

commented Jul 22, 2019

@dimitrispapadimitriouudemy Thanks for your feedback, you're totally right. Mutating is not FP-like. I've updated the implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.