Amit Erandole
Amit Erandole

Reputation: 12281

Why isn't my Ramda pipe function not working with filter?

I have a curried function which I am using in a composition and this works:

const getClubs = R.filter(R.propEq('suit', 'CLUBS'))

This is taking in an array of card objects and filtering them by their suit.

But when I try to unnest this function call and turn it into a pipe:

const getClubs = R.pipe(R.filter, R.propEq('suit', 'CLUBS'))

...this doesn't work anymore and I don't even get any errors. What am I doing wrong with my pipe or filter functions?

Here is a working version of my code

Toggle between line no.8 and line no.9 to see the problem I am describing above

Upvotes: 1

Views: 2002

Answers (1)

Scott Sauyet
Scott Sauyet

Reputation: 50807

This has at least two problems. First, you're confusing compose and pipe. They are very similar, but they apply their functions in the opposite order.

pipe(g, f)(x);    //=> f(g(x))

compose(g, f)(x); //=> g(f(x))

So if you want an equivalent of filter(propEq('suit', 'CLUBS')), then you need to write one of the following instead of R.pipe(R.filter, R.propEq('suit', 'CLUBS')):

R.pipe(R.propEq('suit', 'CLUBS'), R.filter)
// or
R.compose(R.filter, R.propEq('suit', 'CLUBS'))

But the second problem is more fundamental. pipe and compose do not pass one item of their list of function to another one. Instead, they return functions in which the first function is called against the data supplied, the second one is called against the result of the first, the third is called against the result of the second, the fourth against the result of the third, etc.

But filter needs two parameters, a predicate function and a list of values.

Your filter(propEq('suit', 'CLUBS')) is passing filter(propEq('suit', 'CLUBS')), a function of one argument due to currying, to filter, which needs a one-argument function and a list of values. Because we pass just the first, we get back a function that takes the list of values and filters it down to the matching ones.

When you try, say pipe(propEq('suit', 'CLUBS'), filter), and call the resulting function with a list called cards, you pass cards to propEq('suit', 'CARDS'), and since cards is a list without a suit property, it returns false. You then call filter with this false value. Since this curried function requires two parameters, you get back a function looking for a second parameter. It's a useless function, though, because the first argument, false is not a predicate function.

I hope that makes sense. I didn't get much sleep last night, and I'm not quite sure what's sensible. :-)

Upvotes: 5

Related Questions