luobotang

柯里化还是偏函数应用?

原文链接: medium.com

柯里化还是偏函数应用

偏函数应用与柯里化的区别

很多刚刚了解函数式编程的人会对偏函数应用(partial application)和柯里化(currying)之间的区别感到困惑。实际上,直到现在也很少在 JavaScript 中看到柯里化的实际使用,许多叫 curry() 的工具函数并不是柯里化函数。它们其实是偏函数!

如果你也不清楚区别,本文会为你梳理清楚,不过让我们搞清楚一些词语:

定义

应用: 将函数应用于参数,以得到返回值的过程。

偏函数应用: 将函数应用于其部分参数的过程。返回的偏函数在之后被使用。也就是说,一个函数接收一个有多个参数的函数,返回一个需要较少参数的函数。偏函数将一到多个参数在内部固定,然后返回新函数,返回的函数接收剩余的参数完成函数的应用。

柯里化: 输入一个有多个参数的函数, 返回一个只接收单个参数的函数。

这有什么关系呢?

James Coglan 的演讲会帮助你理解:

James 讨论的特性依赖于函数类型一致性。函数有类型。举例来说,函数接收函数和数组,返回数组(例如,Function.prototype.map()):

(fn, array) -> array

  • 偏函数应用 会也可能不会有可预期的返回类型

  • 柯里化函数始终返回另一个具有单个参数而其他参数被指定的函数。

James 讨论的重要的东西都依赖于 函数类型一致性。例如他提到 promise 可以帮助程序逻辑抽象对时间的依赖。

Promise 可以做到是因为它提升了你调用的函数,使得其返回类型始终一致:所有返回 promise 的函数返回了相同的类型,这意味着你可以用标准化的方式来使用它们。James 提到了 promise 带来的各种好处。

这种情况下,promise 是 函子(functor) (一个巧妙的词,意思是“可以被映射的东西”,例如,数组。参考:可应用的函子(applicative functor))的容器,可以为处理数据提供标准化的方法,而无需考虑数据的类型。

警告: google 下函数式编程的术语会很吓人,不过相比其学术名称,它们其实很简单。

通过处理 容器 而非 容器中的值,你可以为任何使用 *容器接口 的东西创建很多一般的 到处可以使用的函数

和 promise 类似,*科里化函数返回容器,这提供了相同的接口。具体是指,作为容器的返回函数。你可以继续调用返回的函数,直到所有参数都传入后返回最终的值。

换句话说,柯里化函数时可以提升所有参数的函数,使得可以用标准化的方式处理这些参数。

最常见的使用提升的方式是 函数组合(function composition),例如,c(x) = f(g(x))。函数组合将一个函数的返回值传给另一个函数作为参数。由于一个函数只能返回一个值,可以接收返回值的函数必定是一元的。

此外,柯里化函数有内置的迭代器机制:柯里化函数每次应用一个参数,不会做超出一个参数外的工作。调用返回的函数也就是告诉函数来进行下一步处理。

例如,柯里化函数 a(b)(c),不会立即调用 c,可以是这样的:

const next = a(b);
doSomeStuff().then(() => next(c));

你应该对偏函数应用和柯里化的区别,以及为什么要对函数执行柯里化有更清楚的理解了。

柯里化在函数式编程中的最常见的应用是让组合函数变得简单。关于这个话题,可以看 “Master the JavaScript Interview: What is Function Composition?”