Skip to content Skip to sidebar Skip to footer

Pass Result Of Functional Chain To Function

If I have an array someArray that I first want to do some operations on and then pass that result to a function arrfun that takes an array as an argument. Like the following let ar

Solution 1:

In the above scenario I would like to avoid having to assign an intermediary variable to be passed to arrfun.

Are you overlooking this simple, straightforward expression ?

let result = arrfun(someArray.filter(foo).map(bar))

right-to-left function composition

Or maybe you wish for classic (right-to-left) function composition?

constcompose = (f,...fs) => x =>
  f === undefined ? x : f(compose(...fs)(x))

constfilter = f => xs =>
  xs.filter(x =>f(x))

constmap = f => xs =>
  xs.map(x =>f(x))

constfoo = x =>
  x > 3constbar = x =>
  x * x
  
constarrfun = xs =>
  xs.reverse()

const myfunc =
  compose(arrfun, map(bar), filter(foo))

let someArray = [1,2,3,4,5,6]

let result = myfunc(someArray)

console.log(result)
// [ 36, 25, 16 ]

left-to-right function composition

The same answer as above using left-to-right function composition

constcompose = (f,...fs) => x =>
  f === undefined ? x : compose(...fs)(f(x))

constfilter = f => xs =>
  xs.filter(x =>f(x))

constmap = f => xs =>
  xs.map(x =>f(x))

constfoo = x =>
  x > 3constbar = x =>
  x * x
  
constarrfun = xs =>
  xs.reverse()

// notice order of functionsconst myfunc =
  compose(filter(foo), map(bar), arrfun)
  
let someArray = [1,2,3,4,5,6]

let result = myfunc(someArray)

console.log(result)
// [ 36, 25, 16 ]

Identity functor

I dont think wrapping the entire thing scales in terms of readability. Imagine that you have to chain some more stuff to arrfun and then wrap that thing in yet another function.

You should see this answer I wrote about the Identity functor - This gives you a chainable interface but doesn't touch native prototypes

constIdentity = x => ({
  runIdentity: x,
  map: f =>Identity(f(x))
})

constfoo = x =>
  x > 3constbar = x =>
  x * x
  
constarrfun = xs =>
  xs.reverse()

constmyfunc = xs =>
  Identity(xs)
    .map(xs => xs.filter(foo))
    .map(xs => xs.map(bar))
    .map(xs =>arrfun(xs))
    .runIdentitylet someArray = [1,2,3,4,5,6]

let result = myfunc(someArray)

console.log(result)
// [ 35, 25, 16 ]

Of course if you keep filter and map as we defined before, it cleans up the definition of myfunc

constIdentity = x => ({
  runIdentity: x,
  map: f =>Identity(f(x))
})

constfilter = f => xs =>
  xs.filter(x =>f(x))

constmap = f => xs =>
  xs.map(x =>f(x))

constfoo = x =>
  x > 3constbar = x =>
  x * x
  
constarrfun = xs =>
  xs.reverse()

constmyfunc = x =>
  Identity(x)
    .map(filter(foo))
    .map(map(bar))
    .map(arrfun)
    .runIdentitylet someArray = [1,2,3,4,5,6]

let result = myfunc(someArray)

console.log(result)
// [ 35, 25, 16 ]

And don't get hung up on foo and bar being defined up front. We can use lambda expressions directly within myfunc if you wanted to

const myfunc = xs =>
  Identity(xs)
    .map(xs => xs.filter(x => x > 3))
    .map(xs => xs.map(x => x * x))
    .map(arrfun)
    // or skip defining arrfun somewhere else and just ...// .map(xs => xs.reverse())
    .runIdentity

Solution 2:

You could compose your manipulator function and your result function first as reusable functions. Like:

let arr = [1,2,3,4,5];
const manipulatorFn = arr => arr.map(item => item +1);
const arrFunc = (arr, fn) =>fn(arr);

or if you want to do some more stuff in the arrFunc

const arrFunc = (arr, fn) => {
  let a = fn(arr);

  // do some more stuff with areturn a;
};

now you can fetch your result

let result = arrFunc(arr, manipulatorFn);

Post a Comment for "Pass Result Of Functional Chain To Function"