0%

函数柯里化


一起学习一下函数柯里化,感谢百度上各位大佬们的无私奉献

什么是柯里化

柯里化,是函数式编程的一个重要概念。它既能减少代码冗余,也能增加可读性。另外,附带着还能用来装逼。

先给出柯里化的定义:在数学和计算机科学中,柯里化是一种将使用多个参数的一个函数转换成一系列使用一个参数的函数的技术。

理论上的东西总是抽象的,直接看最简单的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 普通的add函数
function add(x, y) {
return x + y
}

// Currying后
function curryingAdd(x) {
return function (y) {
return x + y
}
}

add(1, 2) // 3
curryingAdd(1)(2) // 3

实际上就是把add函数的x,y两个参数变成了先用一个函数接收x然后返回一个函数去处理y参数。现在思路应该就比较清晰了,就是只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。

例如有一个简单的加法函数,他能够将自身的三个参数加起来并返回计算结果。

1
2
3
function add(a, b, c) {
return a + b + c;
}

那么add函数的柯里化函数_add则可以如下:

1
2
3
4
5
6
7
function _add(a) {
return function(b) {
return function(c) {
return a + b + c;
}
}
}

下面的运算方式是等价的。

1
2
add(1, 2, 3);
_add(1)(2)(3);

靠眼力封装的柯里化函数自由度偏低,柯里化通用式具备更加强大的能力。因此我们需要知道如何去封装这样一个柯里化的通用式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 简单实现,参数只能从右到左传递
function curry(fn, args) {
// 获取函数需要的参数长度
let length = fn.length;
args = args || [];
return function() {
let subArgs = args.slice(0);
// 拼接得到现有的所有参数
for (let i = 0; i < arguments.length; i++) {
subArgs.push(arguments[i]);
}
// 判断参数的长度是否已经满足函数所需参数的长度
if (subArgs.length >= length) {
// 如果满足,执行函数
return fn.apply(this, subArgs);
} else {
// 如果不满足,递归返回科里化的函数,等待参数的传入
// 如果参数个数小于最初的func.length,则递归调用,继续收集参数
return curry.call(this, fn, subArgs);
}
};
}

如果使用es6的语法,就更简单了

1
2
3
function curry(fn, ...args) {
return fn.length <= args.length ? fn(...args) : curry.bind(null,fn, ...args);
}

以上就是我对函数柯里化的一些理解,如果文章由于我学识浅薄,导致您发现有严重谬误的地方,请一定在评论中指出,我会在第一时间修正我的博文,以避免误人子弟。

-------------本文结束感谢您的阅读-------------
没办法,总要恰饭的嘛~~