Create a gist now

Instantly share code, notes, and snippets.

@ensob /lens.js
Last active Apr 3, 2018

What would you like to do?
Diving inside lenses
// A closer peek under lenses, simple implementation of the lenses.
const lens = (getter, setter) => ({
getter,
setter
});
const lensProp = property =>
lens(prop(property), assoc(property));
const lensPath = path =>
lens(pathView(path), pathSet(path))
const prop = key =>
object =>
object[key]
const assoc = key =>
value =>
object =>
Object.assign({}, object, {[key]: value})
const pathView = paths =>
obj => {
let maybeObj = obj;
paths.forEach((_, index) =>
maybeObj = maybeObj[paths[index]])
return maybeObj;
}
const pathSet = path =>
value =>
object => {
if (path.length === 0)
return value;
const property = path[0];
const child = Object.prototype.hasOwnProperty.call(object, property) ?
object[property] :
Number.isInteger(path[1]) ? [] : {};
val = pathSet(path.slice(1))(value)(child);
return Array.isArray(object) ?
Object.assign([...object], {[property]: value}) :
assoc(property)(value)(object);
}
const view = (lens, obj) =>
lens.getter(obj)
const set = (lens, val, obj) =>
lens.setter(val)(obj)
const over = (lens, fmap, obj) =>
set(lens, fmap(view(lens, obj)), obj);
// pretty console.log object
const logObjs = (...objs) => objs.forEach(obj => console.log(JSON.stringify(obj, null, 2)))
// curried Array.property.map()
const mapOver = fn =>
data =>
data.map(fn)
// usage example
const object = {
property: 'some value',
issue: {
name: 'nested',
deep: [
{ name: "Brian", lastName: "Baker" },
{ name: "Greg", lastName: "Graffin" },
{ name: "Brett", lastName: "Gurewitz" }]
}
}
// create a couple of lenses
const issueLens = lensProp('issue')
const nameLens = lensProp('name')
// first class toUpperCase
const toUpper = str => str.toUpperCase()
const lensOverToUpperCase = lens =>
str =>
over(lens, toUpper, str)
const nameToUpper = lensOverToUpperCase(nameLens)
// massage an object
const massagedObject = over(lensPath(['issue','deep']), mapOver(nameToUpper), object)
logObjs(
object,
massagedObject
)
@outbreak

This comment has been minimized.

Show comment Hide comment
@outbreak

outbreak Feb 27, 2018

Maybe, this will be cleaner?

const over = (lens, fmap, obj) =>
  lens.setter(fmap(lens.getter(obj))(obj);

Maybe, this will be cleaner?

const over = (lens, fmap, obj) =>
  lens.setter(fmap(lens.getter(obj))(obj);
@ensob

This comment has been minimized.

Show comment Hide comment
@ensob

ensob Mar 7, 2018

Yes, very much, thank you @outbreak for pointing that. 👍
Also, If you have not seen, this gist is created for the blog post I wrote earlier
https://blog.codecentric.de/en/2018/02/zooming-lenses-lenses-js-land/
check it out if you are not 😃

Owner

ensob commented Mar 7, 2018

Yes, very much, thank you @outbreak for pointing that. 👍
Also, If you have not seen, this gist is created for the blog post I wrote earlier
https://blog.codecentric.de/en/2018/02/zooming-lenses-lenses-js-land/
check it out if you are not 😃

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