JAVAScript柯里化、部分应用参数终极理解

一、柯里化

在定义柯里化、部分应用参数的概念前,首先必须对闭包有深入的了解和定义,闭包一句话说清楚:函数返回值为函数。

柯里化的定义:将多参函数分解为按步骤接受单个参数的函数,如下代码:

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进阶的基础,在函数式编程中是极其重要一环。函数式编程主要讲究数据的不变性、集合操作、尾递归等。

相关推荐