I have an object and want to update each value in an array inside of the object using some other object member. Here is what I am attempting:
import * as R from 'ramda'
const obj = {
array: [ 1, 2, 3 ],
incrementBy: 0
};
const doIncrement = R.curry((inc,val) => {
return val+inc;
});
const incrementLens = R.lensProp('incrementBy');
const setIncrementToOne = R.set(incrementLens,1);
const newObj = setIncrementToOne(obj);
const arrayLens = R.lensProp('array');
const incrementA = R.over(arrayLens, R.map(doIncrement(1)));
const incrementB = R.pipe(
setIncrementToOne,
R.chain(
R.over(arrayLens, R.map(doIncrement)),
R.view(incrementLens)
)
)
console.log(JSON.stringify(incrementA(newObj))); // works: {"array":[2,3,4],"incrementBy":1}
console.log(JSON.stringify(incrementB(obj))); // does not work (TypeError: Cannot read property 'fantasy-land/map' of undefined)
Version A obviously works as I access the array directly and map my curried function over it. In version B, however, I am unsure of the order of things; what I've tried now does not appear to pass the value from R.view
to the curried function appropriately.
(NB. that the use case is more complex, I would just like to understand how I can work with curried functions, maps and lenses simultaneously.)
When R.chain
is applied to functions - chain(f, g)(x)
is equivalent to f(g(x))(x)
- applying function g
on value 'x', returning, and then applying function f
on the result of g(x)
and then on value x
.
In your case:
g(x)
( R.view(incrementLens)
) is 1 f
( R.over(arrayLens, R.map(doIncrement))
) is a function that waits for the value (not another function) Applying f
( R.over...
) on g(x)
applies a lens on a non object value, and even if it was an object the result would have been another value, which means that you don't have a function to apply to on the result of setIncrementToOne
in the pipe.
The result of g(x)
in this case needs to be a function, that can be used by R.over
with the arraylens
- to get the R.over(arrayLens, R.map(R.add(1)))
, which is identical to incrementA
.
Note: I've replaced doIncrement
with R.add
, which does the same thing.
const obj = { array: [1, 2, 3], incrementBy: 0 }; const incrementLens = R.lensProp('incrementBy'); const setIncrementToOne = R.set(incrementLens, 1); const newObj = setIncrementToOne(obj); const arrayLens = R.lensProp('array'); const incrementB = R.pipe( setIncrementToOne, R.chain( R.over(arrayLens), R.pipe(R.view(incrementLens), R.add, R.map) ) ) const incrementA = R.over(arrayLens, R.map(R.add(1))); console.log(JSON.stringify(incrementA(newObj))); // works: {"array":[2,3,4],"incrementBy":1} console.log(JSON.stringify(incrementB(obj))); // works: {"array":[2,3,4],"incrementBy":1}
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.