J. Hesters
J. Hesters

Reputation: 14816

Ramda: Confused about pipe

I'm learning functional programming in JS and I'm doing it with Ramda.

I'm trying to make a function that takes parameters and returns a list. Here is the code:

const list = R.unapply(R.identity);

list(1, 2, 3); // => [1, 2, 3]

Now I tried doing this using pipe:

const otherList = R.pipe(R.identity, R.unapply);

otherList(1,2,3);
// => function(){return t(Array.prototype.slice.call(arguments,0))}

Which returns a weird function.

This:

const otherList = R.pipe(R.identity, R.unapply);

otherList(R.identity)(1,2,3); // => [1, 2, 3]

works for some reason.

I know this might be a newbie question, but how would you construct f(g(x)) with pipe, if f is unapply and g is identity?

Upvotes: 0

Views: 195

Answers (3)

Scott Sauyet
Scott Sauyet

Reputation: 50807

It looks as though you really are thinking of pipe incorrectly.

When you use unapply(identity), you are passing the function identity to unapply.

But when you try pipe(identity, unapply), you get back a function that passes the results of calling identity to unapply.

That this works is mostly a coincidence: pipe(identity, unapply)(identity). Think of it as (...args) => unapply(identity(identity))(...args). Since identity(identity) is just identity, this turns into (...args) => unapply(identity)(...args), which can be simplified to unapply(identity). This only means something important because of the nature of identity.

Upvotes: 2

customcommander
customcommander

Reputation: 18941

You would use unapply to transform a function that would normally take its arguments as an array into a function that can take any number of positional arguments:

sum([1, 2, 3]); //=> 6
unapply(sum)(1, 2, 3) //=> 6

This allows you to, among many other things, map over any number of positional arguments:

unapply(map(inc))(1, 2) //=> [2, 3]
unapply(map(inc))(1, 2, 3) //=> [2, 3, 4]
unapply(map(inc))(1, 2, 3, 4) //=> [2, 3, 4, 5]

identity will always return its first argument. So unapply(identity)(1,2) is the same as identity([1,2]).

If your end goal was to create a function that returns a list of its arguments, I don't think you needed pipe in the first place. unapply(identity) was already doing that.

However, if what you need to do is to make sure that your pipe gets its parameters as a list, then you simply need to wrap pipe with unapply:

const sumplusplus = unapply(pipe(sum, inc, inc));
sumplusplus(1, 2, 3); //=> 8

Upvotes: 1

Ori Drori
Ori Drori

Reputation: 192317

Read the R.unapply docs. It's a function that gets a function and returns a function, which can take multiple parameters, collect it to a single array, and pass it as the parameter for the wrapped function.

So in the 1st case, it converts R.identity to a function that can receive multiple parameters and return an array.

In the 2nd case, R.unapply gets the result of R.identity - a single value, and not a function. If you pass R.identity as a parameter to the pipe, R.unapply gets a function and return a function, which is similar to the 1st case.

To make R.unapply work with R.pipe, you need to pass R.pipe to R.unapply:

const fn = R.unapply(R.pipe(
  R.identity
))

const result = fn(1, 2, 3)

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

Upvotes: 2

Related Questions