什么是函數(shù)柯里化?
在計(jì)算機(jī)科學(xué)中,柯里化(Currying)是把接受多個(gè)參數(shù)的函數(shù)變換成接受一個(gè)單一參數(shù)(最初函數(shù)的第一個(gè)參數(shù))的函數(shù),并且返回接受余下的參數(shù)且返回結(jié)果的新函數(shù)的技術(shù)。這個(gè)技術(shù)由 Christopher Strachey 以邏輯學(xué)家 Haskell Curry 命名的,盡管它是 Moses Schnfinkel 和 Gottlob Frege 發(fā)明的。
在直覺上,柯里化聲稱“如果你固定某些參數(shù),你將得到接受余下參數(shù)的一個(gè)函數(shù)”。所以對(duì)于有兩個(gè)變量的函數(shù)y,x,如果固定了 y = 2,則得到有一個(gè)變量的函數(shù) 2,x。
舉個(gè)例子:
function multi(a,b){
return a * b;
}
這是一個(gè)求兩個(gè)數(shù)字的乘積的簡單函數(shù),每次調(diào)用時(shí)需要傳入兩個(gè)參數(shù),但是如果我要求5的倍數(shù),每次要重復(fù)輸入
multi(5,1);
multi(5,2);
...
發(fā)現(xiàn),這個(gè)5,是否可以不用每次輸入呢?改造一下這個(gè)函數(shù)
function multiNum(a){
return function(b){
return a * b;
};
}
var multiFive = multiNum(5);
multiFive(3); //返回15
通過對(duì)multi函數(shù)的包裝,只要調(diào)用multiFive,傳入一個(gè)參數(shù)就可以實(shí)現(xiàn)5的乘積。
這里的multiFive函數(shù)就是柯里化multi后的函數(shù)。
通用表達(dá)式:
function currying(fn){
var arg = [].slice.call(arguments,1);
return function(){
var newArg = [].slice.call(arguments);
var finalArg = arg.concat(newArg);
return fn.apply(null,finalArg);
}
}
這里的currying函數(shù)就是柯里化的通用表達(dá)式??吕锘幌轮暗膍ulti函數(shù):
var curryMulti = currying(multi,5);
curryMulti(3); //返回15
柯里化作用
1.提高適用性,參數(shù)復(fù)用
上面的curryMulti例子可以看出,柯里化multi之后,只需要傳入一個(gè)參數(shù)就可以實(shí)現(xiàn)5的倍數(shù)。
2.延遲計(jì)算
下面是一個(gè)求和的函數(shù):
var add = function(){
var sum = 0;
for(var i = 0,len= arguments.length; i< len ;i++){
sum += arguments[i]
}
return sum;
}
下面是一個(gè)延遲執(zhí)行的柯里化函數(shù):
var curryDelay = function(fn){
var args=Array.prototype.slice.call(arguments,1);
var ary=args;
return function(){
if(arguments.length==0){
return fn.apply(null,ary);
}else{
ary=ary.concat(Array.prototype.slice.call(arguments));
return arguments.callee;
}
}
}
對(duì)add函數(shù)進(jìn)行柯里化:
curryDelay(add,3,4,5,6)(); //返回18
通過柯里化函數(shù)后,curryDelay只在參數(shù)為空時(shí)才會(huì)執(zhí)行,返回運(yùn)行結(jié)果。