Ramda lensPath

node v0.12.18
version: 1.0.3
endpointsharetweet
Abstract: Build a utility function that takes an object path, and constructs a Lens for it.
Someone asked in gitter.im for an alternative to `assocPath` that takes a function instead of a value. I recommended Lenses, e.g.
var R = require('ramda'); var myObj = { a: { b: 2 } }; var aLens = R.lensProp('a'); var bLens = R.lensProp('b'); var overA = R.over(aLens); var overB = R.over(bLens); var myFn = R.inc; overA(overB(myFn))(myObj); //=> { a: { b: 3 } }
@CrossEye mentioned an improvement to the example above. Lenses are composable!! O.O
var deepLens = R.compose(aLens, bLens); R.over(deepLens, myFn, myObj) //=> { a: { b: 3} }
Let's see if we can do better.
Attempt 1: Create one lens for the overall object path.
// [String] -> Lens s a var lensPath = function (path) { var getter = R.path(path); var setter = R.assocPath(path); return R.lens(getter, setter); } var deepLens = lensPath(['a', 'b']); var result = R.over(deepLens, myFn, myObj); console.log(result, myObj);
And my work here is done. (>.>)
var toJson = R.nAry(1, JSON.stringify); var test = R.curry(function (input, fn, expected, name) { var actual = fn(input); var passes = R.equals(expected, actual); if (passes) return R.concat(name, ': pass'); else return R.join(' ', [name, ': fail -- expected: ', toJson(expected), ' -- actual: ', toJson(actual)]); }); var testWithObj = test(myObj); var testView = testWithObj(R.view(deepLens), 2, 'test view');
var expected = { a: { b: 4 } }; var testSet = testWithObj(R.set(deepLens, 4), expected, 'test set');
var expected = { a: { b: 3 } }; var testOver = testWithObj(R.over(deepLens, R.inc), expected, 'test over');
Loading…

no comments

    sign in to comment