奇怪的函数语法

7

我看到了一个奇怪的函数,大概长这个样子:

const x = (a) => (b) => a + b;

console.log(x(1)(2))

输出结果是3,我知道这是一个返回一个函数的函数,而且a和b都在同一作用域内,但我有以下问题:
  1. 这在实际生活中如何使用?
  2. 与使用具有两个参数的函数相比,使用此方法(对于单行函数)有什么优点?

4
Currying是一种将函数转换为接受单个参数并返回一个新函数的技术。这些新函数可以接受余下的参数,或者返回结果。Currying的名字来自于Haskell Curry的名字。 - melpomene
1
这只是一个例子。就这个特定的例子而言,它完全没有用处,只会让人感到困惑。 - farvilain
1
看看这个 - meyi
3个回答

8
使用此闭包,您可以获取一个具有常量值以供稍后添加的函数。
“这在现实生活中如何使用?”
您可以将返回的函数用于数组的映射。
“不使用具有2个参数的函数,而是使用这种方法(用于单行函数)的好处是什么?”
这是一种更加简洁和实用的方法。

const
    x = a => b => a + b,
    add5 = x(5);

console.log([1, 2, 3].map(add5));


是的,现在我明白它的用途了。我会更深入地研究柯里化。谢谢 :) - fredtux

3

让我们给那个函数取一个更好的名字:

const add = (a) => (b) => a + b

稍后您可以编写

[1, 2, 3, 4] .map (add (5)) //=> [6, 7, 8, 9]

这段文字比较易懂

[1, 2, 3, 4] .map ((n) => 5 + n) //=> [6, 7, 8, 9]

在 Promise 的一系列 .then() 调用链中,这非常方便:

  return fetchList (param)
    .then (map (add (5)))
    .then (filter (lessThan (8)))
    .then (average)

(当然,这需要柯里化函数addlessThanmapfilter,以及一些简单的average函数。)

将其与以下内容进行比较:

  return fetchList (param)
    .then (xs => xs.map (x => add (5, x)))
    .then (xs => xs.filter (x => lessThan (8, x)))
    .then (average)

请注意, average 在这两个版本中起作用的原因是它只接受一个参数。科里化的一个主要优点是将函数转换为只接受单个参数的函数。这使得某种编码风格更容易实现。

2
Nina 给出了一个很好的答案。我将提供另一个稍微高级一些的例子,其中这样的闭包在代码的清晰度方面非常有帮助。让我们将函数组合成前缀检查器,然后根据需要重复使用它:

//given a word, check if a string s starts with this word
const literal = word => s => s && s.startsWith(word);

//allow to combine 2 literals with OR    
const either = (p1, p2) => s => p1(s) || p2(s);

//allow to combine N literals
const any = (...parsers) => parsers.reduce(either);

//create a parser
const check = any(literal('cat'),literal('dog'),literal('cow'));

console.log('cat: ' + check('cat'));
console.log('dog: ' + check('dog is smart'));
console.log('cow: ' + check('cow 123'));
console.log('banana: ' + check('banana'));

实际上,它是一个简化的解析器组合器(不,还没有单子)。通过扩展这种方法,您可以为自己的编程语言创建解析器,并且它将是可维护和快速的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接