gingitsune
gingitsune

Reputation: 13

Pass a list of functions to pipe or compose in Ramda.js

About functions that take multiple arguments.

In particular I assume "pipe" and "compose". They take multiple functions as arguments.

At this time, I want to pass them a list of multiple functions.

In Ramda.js Normally:

const piped = R.pipe(R.inc, R.negate);

I wanna like this:

const funcs = [R.inc, R.negate];
const piped = R.pipe(funcs);

I'm also thinking about passing a list of partially applied functions

const funcs = [R.add (1), R.pow (2)];

The functions in these lists have no name property. So I wondered if a solution could be found by binding these Ramdajs functions and partially applied functions to variables. But they didn't seem so smart.

This is my first experience in English and in stack overflow. And I am sorry in ugly English because it is a mechanical translation. How can I solve this problem, please tell me the solution. Thank you.

Upvotes: 1

Views: 1889

Answers (3)

jaume mila
jaume mila

Reputation: 31

The simplest method to convert an array into multiple parameters is destructuring. Add "..." in front of the parameter:

const funcs = [R.inc, R.negate];
const piped = R.pipe(...funcs);

More about destructuring here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

Upvotes: 2

Nikos M.
Nikos M.

Reputation: 8345

Ramda.js functions are normal javascript functions so Function.call and Function.apply methods are available.

So the solution to your problem is to use .apply method to apply multiple arguments (that are a list):

example:

const funcs = [R.inc, R.negate];
const piped = R.pipe.apply(R, funcs);

There is also a Ramda.apply as well (which you can check in the Ramda documentation) but native Function.apply method solves the problem elegantly and natively (note according to documentation of the pipe function there is no mention of using a specific context as there is for some other functions in Ramda documentation ).

Answer to comment:

R.apply has exactly same issues with bound context as native apply method has (according to Ramda documentation). So the issue of context of apply method is mostly irrelevant and of minor importance.

Upvotes: -1

user5536315
user5536315

Reputation:

What you actually want is to fold a list of functions with the reverse function composition combinbator (aka contravariant functor):

const inc = x => x + 1;
const sqr = x => x * x;

const reduce1 = f => xs =>
  xs.reduce(f);
  
const contra = (g, f) => x =>
  f(g(x));

console.log(
  reduce1(contra) ([inc, inc, inc, sqr]) (1)); // 16

This works only for non-empty arrays. We need a fold with an accumulator to make the partially applied fold reduce1(contra) a total function:

const inc = x => x + 1;
const sqr = x => x * x;
const id = x => x;

const reduce = f => acc => xs =>
  xs.reduce(f, acc);
  
const contra = (g, f) => x =>
  f(g(x));
  
const pipen = reduce(contra) (id);

console.log(
  pipen([inc, inc, inc, sqr]) (1)); // 16

console.log(
  pipen([]) (1)); // 1

In Ramda though, using R.apply is totally fine. But note that this function is specific to Ramda.

Upvotes: 1

Related Questions