【问题标题】:What is the different between curry and partial function in Ramda?Ramda 中的 curry 和偏函数有什么区别?
【发布时间】:2017-04-26 23:51:23
【问题描述】:

似乎currypartial 函数做同样的事情。 (也许唯一的区别是参数的数量)

这只是为了方便还是有充分的理由让两个功能做类似的事情。

【问题讨论】:

标签: javascript functional-programming ramda.js


【解决方案1】:

正如您简要提到的,curry 函数可以接受一个带有 n 个参数的函数并返回 n 个带有一个参数的函数。柯里化是将函数组合成高阶函数的重要工具。

函数的部分应用是一种柯里化。事实上,如果你查看 Ramda source code 你会发现 partial 函数是使用 curry 函数实现的。

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));
    });
  });
};

另外,请查看this question,从根本上解释不同之处。

【讨论】:

  • 这不正确:“函数的部分应用是一种柯里化。”柯里化是将(a, b, c) -> d 等类型的函数转换a -> b -> c -> d 类型的函数。
【解决方案2】:

来自更广泛的 FP 社区的许多答案可能会让您有些误会。在我看来,Ramda 的柯里化将 ML 风格语言的柯里化精神带到了 Javascript 中,但并不完全相同。

部分应用程序在 Ramda 中可能是相当标准的。 (免责声明:我是 Ramda 的作者之一。)它也更容易描述。 Ramda 的partial 函数接受n 参数的函数和k 参数列表(对于某些0 < k < n),并返回n - k 参数的新函数,它将使用您的新参数调用原始函数,并且原来的:

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

返回的函数只是剩余参数的简单函数。如果你用太少调用它,它会像你用太少调用原始函数一样。

柯里化是一个稍微不同的故事。在many languages 中,curry 函数会将n 参数的函数转换为1 参数函数的嵌套序列,因此(a, b, c) => f(a, b, c) 转换为a => (b => (c => f(a, b, c)),可以毫无混淆地写为a => b => c => f(a, b, c) .在 Ramda 中,我们更灵活一点,允许您在一次调用中提供尽可能多的参数,每次都返回一个函数,直到您提供了足够的总参数来满足原始函数,此时我们调用它并返回该值。用例子可能更容易解释:

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

因为curry 灵活得多,所以我自己很少使用partial。但是有些人,咳咳,偏向

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-09
    • 2019-01-25
    • 2020-11-27
    相关资源
    最近更新 更多