什么是“函数柯里化”
curry的概念:只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。
先看一个简单的例子,add函数接受两个参数,addcurry函数接受一个参数。
1 | // 非柯里化 |
由例子可以看出,所谓的“柯里化“就是将一个多参数的函数,转化成单参数的函数。
函数柯里化的优点
参数复用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// 非柯里化
function check(reg, txt) {
return reg.test(txt);
}
check(/\d+/g, 'test') //false
check(/[a-z]+/g, 'test') //true
// 柯里化后
function checkCurry(reg) {
return function(txt) {
return reg.test(txt);
};
}
const hasNumber = checkCurry(/\d+/g);
const hasLetter = checkCurry(/[a-z]+/g);
console.log(hasNumber('shuliqi11')); // true
console.log(hasNumber('shuliqi')); // false
console.log(hasLetter('1231231')); // false上面的示例是一个正则的校验,正常来说直接调用check函数就可以了,但是如果我有很多地方都要校验是否有数字,其实就是需要将第一个参数reg进行复用,这样别的地方就能够直接调用hasNumber,hasLetter等函数,让参数能够复用,调用起来也更方便
延迟运行
1
2
3
4
5
6
7
8Function.prototype.bind = function (context) {
var _this = this
var args = Array.prototype.slice.call(arguments, 1)
return function() {
return _this.apply(context, args)
}
}像我们js中经常使用的bind,实现的机制就是Curry
如何实现柯里化
我们先看一个例子:这里使用了(ramda, 自行安装)。
1 | var _ = require("ramda"); |
栗子中我们对 add 进行了柯里化,从结果上可以看到当参数为 1 个时返回的是个函数,当参数为 2 个的时候返回函数,当参数为 3 个的时候返回函数执行结果
。
根据上述的小栗子,可以得到,柯里化后的函数
如果接受到全部参数则返回函数执行结果
,否则返回一个柯里化函数
。
1 | function curry(fn) { |
上述伪代码是不是很像递归?
- 递归出口:curry_fn接受到的参数数量等于fn接受参数的数量
- 重复逻辑:return “一个柯里化函数”
于是有了以下简单实现柯里化的代码
1 | function curry(fn, args = []) { |