MattMS
MattMS

Reputation: 1156

Using the same first argument in a Ramda pipe

Is it possible to compose the following function in Ramda?

(a, b) => R.pipe(func1(a), func2(a))(b)

The aim is passing argument a to all functions in the pipe.

My initial thought was the following:

R.pipe(R.juxt([func1, func2]), R.apply(R.pipe))

But this gives TypeError: Cannot read property 'length' of undefined.

Upvotes: 1

Views: 1084

Answers (2)

davidchambers
davidchambers

Reputation: 24846

This is easier to express using S.pipe as it takes an array of functions to compose.

One option is to use R.ap:

> S.pipe(R.ap([S.add, S.mult, S.add], [3]), 10)
42

Another option is to use R.map with S.T, the thrush combinator:

> S.pipe(R.map(S.T(3), [S.add, S.mult, S.add]), 10)
42

You could then wrap one of these in a lambda to create a binary function:

const f = (a, b) => S.pipe(R.ap([S.add, S.mult, S.add], [a]), b);

f(3, 10);  // add(3)(mult(3)(add(3)(10)))
// => 42

Upvotes: 1

Mauricio Poppe
Mauricio Poppe

Reputation: 4876

You have to create a curried version of all the functions, then call the curried version of each with a and finally use b in either R.pipe or R.reduce

Let's say that the functions that need to have a as the first argument are f,g,h (in that specific order) then we want to achieve the following expression

h(a, g(a, f(a, b)))

First of all let's create a curried function which receives two arguments, a single value v and a function fn, when this function receives all its required arguments it will simply return fn(v)

const rev = R.curry((v, fn) => fn(v))

Next we can create the curried versions of the functions with R.map and R.curry

// note the reversed order of the functions
// I'll use R.compose instead of R.pipe
let curriedVersion = R.map(R.curry, [h,g,f]) 

However we also need to use a as the first argument of the curried functions, we could call each curried function with a using R.map but instead we will use our special function rev

const curriedVersion = R.map(R.compose(rev(a), R.curry), [h,g,f]) 

Finally let's use this array of curried functions with R.compose and b

const result = R.compose.apply(undefined, curriedVersion)(b)

One liner (for the functions f,g,h in that specific order):

const solver = (a, b) => R.compose.apply(undefined, R.map(R.compose(rev(a), R.curry), [h,g,f]))(b)

const add = (a, b) => a + b
const sub = (a, b) => a - b
const mul = (a, b) => a * b

const rev = R.curry((v, fn) => fn(v))
const solver = (a, b) => R.compose.apply(undefined, R.map(R.compose(rev(a), R.curry), [mul,sub,add]))(b)

// mul(2, sub(2, add(2, 3)))
// mul(2, sub(2, 5))
// mul(2, -3)
// -6
console.log(solver(2, 3))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.21.0/ramda.min.js"></script>

Upvotes: 0

Related Questions