Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the different between curry and partial function in Ramda?

It seems the curry and partial functions do the exact same thing. (Maybe the only difference is the number of arguments)

Is it just matter of convinience or there is a good reason on having two functions that do kind of similar thing.


1 Answers

A lot of answers from the wider FP community might steer you a little wrong. Ramda's currying seems to me to carry the spirit of currying from ML-style languages into Javascript, but is not strictly the same.

Partial application is probably fairly standard in Ramda. (Disclaimer: I'm one of the Ramda authors.) It's also much easier to describe. Ramda's partial function accepts a function of n arguments and a list of k arguments (for some 0 < k < n), and returns a new function of n - k arguments that will call the original function with your new arguments and the original ones:

const f = (a, b, c, d, e) => a + b + c + d + e;
// f :: a -> b -> c -> d -> e -> a + b + c + d + e

const g = partial(f, [1, 2]);
g.length; //=> 3
g(3, 4, 5); //=> 15
g(3); //=> NaN ≍ 1 + 2 + 3 + undefined + undefined)
// g :: (c, d, e) -> 1 + 2 + c + d + e

The function returned is just a simple function of the remaining parameters. If you call it with too few, it will act as though you called the original function with too few as well.

Currying is a slightly different story. In many languages, a curry function would convert a function of n parameters into a nested sequence of 1-parameter function, so that (a, b, c) => f(a, b, c) transforms into a => (b => (c => f(a, b, c)), which can be written without confusion as a => b => c => f(a, b, c). In Ramda, we are a little more flexible, allowing you to supply as many of the arguments as you choose at a single call, each time returning a function until you have supplied enough total parameters to satisfy the original function, at which point we call it and return that value. It's probably easier to explain with examples:

const f = (a, b, c, d, e) => a + b + c + d + e;
// f :: a -> b -> c -> d -> e -> a + b + c + d + e

const h5 = curry(f);
h5.length; //=> 5

const h3 = h5(1, 2);
h3.length; //=> 3
h3(3, 4, 5); //=> 15

const h2a = h3(3);
h2a.length; //=> 2
h2a(4, 5); //=> 15

const h2b = h5(1, 2, 3);
h2b.length; //=> 2
h2b(4, 5); //=> 15

const h2c = h5(1)(2, 3);
h2c.length; //=> 2
h2c(4, 5); //=> 15

const h2d = h5(1)(2)(3);
h2d.length; //=> 2
h2d(4, 5); //=> 15

const h1a = h3(3, 4);
h1a.length; //=> 1
h1a(5); //=> 15

const h1b = h2a(4);
h1b.length; //=> 1
h1b(5); //=> 15

// h5 :: (a, b, c, d, e) -> a + b + c + d + e
//    :: (a, b, c, d) -> e -> a + b + c + d + e
//    :: (a, b, c) -> (d, e) -> a + b + c + d + e
//    :: (a, b, c) -> d -> e -> a + b + c + d + e
//    :: (a, b) -> (c, d, e) -> a + b + c + d + e
//    :: (a, b) -> (c, d) -> e -> a + b + c + d + e
//    :: (a, b) -> c -> (d, e) -> a + b + c + d + e
//    :: (a, b) -> c -> d -> e -> a + b + c + d + e
//    :: a -> (b, c, d, e) -> a + b + c + d + e
//    :: a -> (b, c, d) -> e -> a + b + c + d + e
//    :: a -> (b, c) -> (d, e) -> a + b + c + d + e
//    :: a -> (b, c) -> d -> e -> a + b + c + d + e
//    :: a -> b -> (c, d, e) -> a + b + c + d + e
//    :: a -> b -> (c, d) -> e -> a + b + c + d + e
//    :: a -> b -> c -> (d, e) -> a + b + c + d + e
//    :: a -> b -> c -> d -> e -> a + b + c + d + e

Because curry is so much more flexible, I rarely use partial myself. But there are people who are, ahem, partial to it.

like image 68
Scott Sauyet Avatar answered Nov 02 '25 10:11

Scott Sauyet



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!