Sequentially apply multiple functions to object using different lenses

Images
Related searches

I would like to perform some updates to an array in an object, and then calculate another parameter based on this update. This is what I tried:

import * as R from 'ramda'

const obj = {
    arr: [
        2,
        3
    ],
    result: {
        sumOfDoubled: 0
    }
};

const double = a => {
    return a*2;
}

const arrLens = R.lensProp('arr');
const res0sumOfDblLens = R.lensPath(['result','sumOfDoubled']);

const calc = R.pipe(
    R.over(arrLens,R.map(double)),
    R.view(arrLens),
    R.sum,
    R.set(res0sumOfDblLens)
);

const updatedObjA = calc(obj);
const updatedObjB = R.set(res0sumOfDblLens,R.sum(R.view(arrLens,R.over(arrLens,R.map(double),obj))),obj);


// what I want: {"arr":[4,6],"result":{"sumOfDoubled":10}}
console.log(JSON.stringify(obj)); //{"arr":[2,3],"result":{"sumOfDoubled":0}}, as expected
console.log(JSON.stringify(updatedObjA)); //undefined
console.log(JSON.stringify(updatedObjB)); //{"arr":[2,3],"result":{"sumOfDoubled":10}}, correct result but the array did not update

I realise that neither approaches will work; approach A boils down to R.set(res0sumOfDblLens,10), which makes no sense as it doesn't have a target object for the operation. Approach B, on the other hand, manipulates the base object twice rather than passing the result of the first manipulation as an input for the second.

How can I achieve this using only one function composition; i.e. apply the double() function to one part of the object, and then passing that updated object as input for calculating sumOfDoubled?

As well as OriDrori's converge solution, you could also use either of two other Ramda functions. I always prefer lift to converge when it works; it feels more like standard FP, where converge is very much a Ramda artifact. It doesn't always do the job because of some of the variadic features of converge. But it does here, and you could write:

const calc = pipe (
  over (arrLens, map (multiply (2))),
  lift (set (res0sumOfDblLens) ) ( 
    pipe (view (arrLens), sum),
    identity
  )
)

But that identity in either of these solutions makes me wonder if there's something better. And there is. Ramda's chain when applied to functions is what's sometimes known as the starling combinator, :: (a -> b -> c) -> (a -> b) -> a -> c. Or said a different way, chain (f, g) //~> (x) => f (g (x)) (x). And that's just what we want to apply here. So with chain, this is simplified further:

const arrLens = lensProp('arr')
const res0sumOfDblLens = lensPath(['result', 'sumOfDoubled'])

const calc = pipe (
  over (arrLens, map (multiply (2))),
  chain (
    set (res0sumOfDblLens), 
    pipe (view (arrLens), sum)
  )
) 

const obj = { arr: [2, 3], result: { sumOfDoubled: 0 }}

console .log (calc (obj))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>const {lensProp, lensPath, pipe, over, map, multiply, chain, set, view, sum} = R </script>

Hottest 'lenses' Answers, Sequentially apply multiple functions to object using different lenses. As well as OriDrori's converge solution, you could also use either of two other Ramda� These are analysed by considering each element sequentially. The image formed by the first is the object for the second, and so on. The same ray tracing and thin lens techniques apply to each lens element. The overall magnification of a multiple-element system is the product of the magnifications of its individual elements.

To get the updated value, and the object, so you can set the new sum, you can use R.converge():

const arrLens = R.lensProp('arr');
const res0sumOfDblLens = R.lensPath(['result', 'sumOfDoubled']);

const calc = R.pipe(
  R.over(arrLens, R.map(R.multiply(2))),
  R.converge(R.set(res0sumOfDblLens), [
    R.pipe(R.view(arrLens), R.sum), 
    R.identity
  ])
);

const obj = { arr: [2, 3], result: { sumOfDoubled: 0 }};

const result = calc(obj);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>

[PDF] Imaging with two lenses, Oblique-ray method, lens-to-lens, no need to find Find intermediate image, use as object for next lens. – lens-to-lens (sequential raytracing)-later in semester Apply imaging formula to first lens Raytracing through several lenses. Achromat lenses are the simplest of these general categories (Fig. 2.2A) and consist of at least two lenses, generally constructed of crown glass and flint glass, and are corrected for axial chromatic aberration for blue and red lights (486 and 656 nm wavelengths, respectively). The chromatic correction is accomplished using “achromatic

Maybe a variant without a lense would be a better fit for your case?

const doubleArr = pipe(
    path(['arr']),
    map(x => x*2)
  )
const newData = applySpec({
  arr: doubleArr,
  result: {
    sumOfDoubled: pipe(
       doubleArr,
       sum
    )
  }
})

Function, Creates a new list iteration function from an existing one by adding two new var nums = [1, 2, 3, -99, 42, 6, 7]; R.apply(Math.max, nums); //=> 42 difference Relation Returns a new list without any consecutively repeating elements. R. equals var xLens = R.lens(R.prop('x'), R.assoc('x')); R.view(xLens, {x: 1, y: 2}); //=> 1� A method is used for imaging applications so that one can simultaneously apply multiple illumination schemes and simultaneously acquire the images, each associated with one of the multiple illumination schemes.

US7683962B2, Digital cameras typically use one of two types of autofocus systems: a In that diagram, light from an object 151 is incident on two small lenses 152 and 153 which Once an image is in focus, the “hill climb” method typically operates over the dynamic range within images by applying gain adjustments to objects as a � A strategy using different aberration coefficients is developed, and a series of diffraction intensity maps is sequentially recorded by a charge-coupled device.

Sequential Application of Glass Coverslips to Assess the , Several studies have linked presbyopia to age-related increase in the intrinsic stiffness of the lens6-11. Stiffness is defined as the resistance of an elastic object to deform under A handful of studies have examined mouse lens stiffness with Two other studies have used the described method to show that� A chirped or frequency modulated sonic wave is passed through a dispersive lens whose focal length varies with frequency. Thus the different frequencies in the sonic wave focus at different depths in the object. The reflected energy is applied to a band pass filter so as to respond to the particular depth being received.

While this works, it does not seem to be running multiple processes; it seems like it's just running in serial (I've tried using Pool(5) with the same result). What am I missing? Are the calls to Popen "blocking"? EDIT: Clarified a little. I need cmd1, then some python command, then cmd2, to execute in sequence on each file.

Comments
  • Whenever you use R.view you perfom a get operation and lose the context, i.e. the Object in your case. I am not familiar with Ramda's optic but AFAIK you just need R.view to calc the sum of the nested array outside the Object and then R.set to set the sum inside the Object. The way you use the functional optic resembles the use of normal getters and setters but lenses are both at the same time.
  • Minor nitpick: You specified the type signature of the applicative functor. The monadic one is (a -> b -> c) -> (b -> a) -> b -> c. Actually you can use ap here since the chained computation doesn't depend on the previous value.
  • @bob: well substituting ap for chain does not work properly. Maybe Ramda gets this wrong, but ap (f, g) //~> (x) => f (x) (g(x)), where chain (f, g) //~> (x) => f (g (x)) (x).
  • If we replace chain with the corresponding lambda o => set(res0sumOfDblLens) (pipe(view(arrLens), sum) (o)) (o) and this in turn with the lambda in applicative style o => set(res0sumOfDblLens) (o) (pipe(view(arrLens), sum) (o)) it is obvious, that set doesn't work properly with its arguments flipped. Hence we need to apply flip so that it gets o => flip(set(res0sumOfDblLens)) (o) (pipe(view(arrLens), sum) (o)).
  • @bob: I started to do that in my previous comment and decided it wasn't worth it. I still have some issues with ap vs chain in a function context, and this actually helped me figure it out... so thanks!
  • @OriDrori: Just as Ramda's map extends beyond simply arrays to any Functor type, chain works with any Chain type. Ramda supplies implementations of map for Array, Object, and Function, and delegates to your map for other types. Similarly, Ramda supplies implementations of chain for Array and Function, also delegating. That this is the starling combinator is not particularly the goal; it's simply the reasonable chain for Function.
  • I'm also using such a pattern converge and identity to get a reference on an object.