柯里化介绍
柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。这个技术由克里斯托弗·斯特雷奇以逻辑学家哈斯凯尔·加里命名的,尽管它是Moses Schönfinkel和戈特洛布·弗雷格发明的。
在直觉上,柯里化声称如果你固定某些参数,你将得到接受余下参数的一个函数。
在理论计算机科学中,柯里化提供了在简单的理论模型中,比如:只接受一个单一参数的lambda演算中,研究带有多个参数的函数的方式。函数柯里化的对偶是Uncurrying,一种使用匿名单参数函数来实现多参数函数的方法。
Currying概念其实很简单,柯里化就是:将一个带有多个参数的函数转换为一次一个的函数的过程。每次调用函数时,它只接受一个参数,并返回一个函数,直到传递所有参数为止。
例如我们需要实现一个求三个数之和的函数:
<script type="text/javascript">反柯里化(uncurrying)
var currying = function(fn) {
var args = Array.prototype.slice.call(arguments, 1);
return function() {
if (arguments.length === 0) {
return fn.apply(this, args); // 没传参数时,调用这个函数
} else {
[].push.apply(args, arguments); // 传入了参数,把参数保存下来
return arguments.callee; // 返回这个函数的引用
}
}
}
var cost = (function() {
var money = 0;
return function() {
for (var i = 0; i < arguments.length; i++) {
money += arguments[i];
}
return money;
}
})();
var cost = currying(cost,10);
cost(100); // 传入了参数,不真正求值
cost(200); // 传入了参数,不真正求值
cost(300); // 传入了参数,不真正求值
console.log(cost()); // 求值并且输出610
</script>
拿到一个柯里化后的函数,却想要它柯里化之前的版本,这本质上就是想将类似f(1)(2)(3)的函数变回类似g(1,2,3)的函数。
代码如下:
<script type="text/javascript">
var currying = function(fn) {
var args = Array.prototype.slice.call(arguments, 1);
return function() {
if (arguments.length === 0) {
return fn.apply(this, args); // 没传参数时,调用这个函数
} else {
[].push.apply(args, arguments); // 传入了参数,把参数保存下来
return arguments.callee; // 返回这个函数的引用
}
}
}
function uncurrying(fn) {
return function(...args) {
var ret = fn;
for (let i = 0; i < args.length; i++) {
ret = ret(args[i]); // 反复调用currying版本的函数
}
return ret; // 返回结果
};
}
var cost = (function() {
var money = 0;
return function() {
for (var i = 0; i < arguments.length; i++) {
money += arguments[i];
}
return money;
}
})();
var curryingCost = currying(cost);
var uncurryingCost = uncurrying(curryingCost);
console.log(uncurryingCost(100, 200, 300)()); // 600
</script>
那么柯里化有什么用途
延迟计算
参数复用
动态生成函数
网友回复