最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - What is the different between curry and partial function in Ramda? - Stack Overflow

programmeradmin1浏览0评论

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.

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.

Share Improve this question asked Dec 12, 2016 at 6:38 user7283346user7283346 2
  • This is almost the same question as What is the difference between currying and partial application only without ramda reference. – lonelyelk Commented Dec 12, 2016 at 10:19
  • @lonelyelk: ... but because Ramda's curry is somewhat non-standard, this might need its own answer. I'll try my own below. – Scott Sauyet Commented Dec 12, 2016 at 16:34
Add a ment  | 

2 Answers 2

Reset to default 10

A lot of answers from the wider FP munity 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.

As you briefly mentioned, curry function can take a function with n arguments and return n functions with one argument. Currying is an essential tool to pose functions into higher order functions.

Partial applications of functions is a type of currying. In fact, if you look into Ramda source code you'll see that the partial function was implemented using curry function.

var _arity = require('./_arity');
var _curry2 = require('./_curry2');


module.exports = function _createPartialApplicator(concat) {
  return _curry2(function(fn, args) {
    return _arity(Math.max(0, fn.length - args.length), function() {
      return fn.apply(this, concat(args, arguments));
    });
  });
};

Also, take a look to this question that explain the different fundamentally.

发布评论

评论列表(0)

  1. 暂无评论