JAVAScript柯里化、部分應用引數終極理解

小龍女先生發表於2016-11-08

一、柯里化

在定義柯里化、部分應用引數的概念前,首先必須對閉包有深入的瞭解和定義,閉包一句話說清楚:函式返回值為函式。

柯里化的定義:將多參函式分解為按步驟接受單個引數的函式,如下程式碼:

var mod = function(a,b){
    return a * b;
}
function curry2(fun){ 
var _funTwo = function(arg){
       return function(two){
           return fun(arg,two); 
       }
   };
   return _funTwo;
}
var _add2 = curry2(mod); 
var result2 = _add2(1)(2);

mod:接受兩個引數,分別為a,b;

curry2:實現柯里化功能函式,由於傳入mod這個引數,返回接受一個引數的閉包;在新閉包的函式上傳入另一個值(b)即可完成mod函式的執行。

無限級柯里化

var mod = function(a,b){
    return a * b;
}
function curry2(fun){ 
   var newVal; 
   var _funTwo = function(arg){
       return function(two){
           if(!two) return newVal;
           newVal = fun(arg,two); 
           return _funTwo(newVal);
       }
   };
   return _funTwo;
}
var _add2 = curry2(mod); 
var result2 = _add2(1)(2)(3)(4)(5)();

1.2、柯里化的應用

a). 利用柯里化增加約束條件,只有通過所有約束條件的資料才最終被執行;

b). 變數不會存在全域性汙染(保護變數的私有性),自由變數(函式內部不定義,但可以訪問的變數,一般情況下是全域性變數,或區域性全域性變數),約束變數(函式內部定義的變數,生命週期在函式內部)。函式(function)依賴自由變數,就會存在自身的返回值不可控的現象,這就是傳說中的共享變數耦合。

c). 無限級柯里化固能實現,但不實用,用柯里化最主要的目的是為最終執行單元增加約束條件(引數分解),約束條件是有限的。

如需要約束條件是動態的,則應該選擇下面介紹的”部分應用引數“

 

二、部分應用引數

部分應用引數的定義:傳入任何多個約束條件,返回接受執行單元和引數的閉包。實現約束條件的預設定。程式碼如下:

function Parit(fun, parg){
            return function(){
                var args = _.toArray(arguments);
                args.splice(0,0,parg);
                return fun.apply(fun,args); //執行後必須返回
            }
        }     
        function condition1(){
            var validators = _.toArray(arguments);
            return function(fun, arg){
                var errors = _.map(validators,function(data,irow){
                    return data(arg) ? [] : [data.name + ' error'];
                });
                if(!_.isEmpty(errors.join())){
                    console.info(errors.join());
                    return;
                    //throw new Error(errors.join());
                }
                return fun.call(fun,arg); //執行後必須返回
            }
        }
        var sqlPre = condition1(_.isNumber); //sqlPre是閉包,需要fun,arg兩個引數
        function uncheckedSqr(n){ return n * n; }

        console.log(sqlPre( uncheckedSqr,10) ); //本質
        var sqr = Parit(sqlPre,uncheckedSqr); //返回一個閉包 uncheckedSqr作為sqlPre的第一個引數傳入
        console.log( sqr('5') );
        console.log( sqr(5) );

2.2、部分引數應用:

a). 實現約束預設定,主要用於驗證模組。

b).部分應用引數與柯里化主要區別於,柯里化每次只接受一個引數,而部分應用引數一次可以接受多個引數;但柯里化與部分應用引數都只能按照引數進行組合

三、總結

a). 柯里化的理解是javascript進階的基礎,在函數語言程式設計中是極其重要一環。函數語言程式設計主要講究資料的不變性、集合操作、尾遞迴等。

相關文章