Javascript 在拉姆达,咖喱和部分功能有什么不同?

Javascript 在拉姆达,咖喱和部分功能有什么不同?,javascript,functional-programming,ramda.js,Javascript,Functional Programming,Ramda.js,看起来和函数的作用完全相同。(可能唯一的区别是参数的数量) 这只是方便的问题,还是有一个很好的理由让两个函数做类似的事情。正如您简要提到的,curry函数可以接受一个有n个参数的函数,并返回n个有一个参数的函数。Curry是将函数组合成高阶函数的基本工具 函数的部分应用是一种套用。事实上,如果您查看Ramda,您将看到partial函数是使用curry函数实现的 var _arity = require('./_arity'); var _curry2 = require('./_curry2'

看起来和函数的作用完全相同。(可能唯一的区别是参数的数量)


这只是方便的问题,还是有一个很好的理由让两个函数做类似的事情。

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

函数的部分应用是一种套用。事实上,如果您查看Ramda,您将看到
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));
    });
  });
};

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

来自更广泛的FP社区的许多答案可能会让你犯一些错误。在我看来,Ramda的咖喱风格似乎将咖喱风格从ML风格的语言带入Javascript,但严格来说并不相同

部分应用程序在Ramda中可能是相当标准的。(免责声明:我是Ramda的作者之一。)它也更容易描述。Ramda的
partial
函数接受一个
n
参数的函数和一个
k
参数列表(对于某些
0
),并返回一个
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
返回的函数只是剩余参数的简单函数。如果调用它的次数太少,它的行为就好像调用原始函数的次数也太少一样

咖喱是一个稍微不同的故事。在中,一个
curry
函数将
n
参数的函数转换成一个嵌套的单参数函数序列,这样
(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
。但是有些人,嗯,偏爱它。

这句话不正确:“函数的部分应用是一种curry。”curry是对
(a,b,c)类型函数的转换->d
转换成类型为
a->b->c->d
的函数。这几乎和没有拉姆达参考的问题一样。@lonelyelk:…但是因为拉姆达的
咖喱
有点不标准,这可能需要它自己的答案。我将在下面尝试我自己的答案。