美文网首页
函数柯里化

函数柯里化

作者: RichardBillion | 来源:发表于2016-06-26 02:06 被阅读92次

    柯里化是什么

    其实就是将原来接受多个参数的函数变成我现在接受一个参数但是返回接受其余参数的函数。有点类似原来用大巴车一次将人们送过去改成现在用小轿车多次将这些人送过去。简单地说,柯里化是一种允许使用部分函数参数构造函数的方式。

    比如定义一个求两者和的方法

    普通方法:
    function sun(a, b) {
        return a + b;
    }
    sum(1, 2); //3
    柯里化方法:
    var sum = function(a) {
        return function(b) {
            return a + b;
        }
    }
    var add = sum(1);
    add(2); //3
    

    柯里化就是纯函数编程的一种体现:接受一个输入,返回一个输出。每传入一个参数调用函数,就返回一个新函数处理剩余的参数。

    柯里化有何用处

    但是目前看来除了多些一步没啥用处啊,继续~
    对于求和问题,更经常遇见的应该是随便给一个数组,来计算它们的和。
    普通方法:

    function sum(a) {
        var arr = [],
            summary = 0;
        if (arguments.length === 1) {
            arr[0] = a;
        } else {
            arr = arr.concat([].slice.call(arguments));
        }
        for (var i = 0, len = arr.length; i < len; i++) {
            summary += arr[i];
        }
        return summary;
    }
    sum(1, 1, 2, 3); //7
    

    柯里化方法:

    function sum(a) {
        var arr = [],
            summary_a = 0,
            summary = 0;
        if (arguments.length === 1) {
            arr[0] = a;
        } else {
            arr = arr.concat([].slice.call(arguments));
        }
        summary_a = arr.reduce(function(prev, cur, index, array) {//此处将for循环替换为reduce只是重温下用法而已,其实完全没必要。。。
            return prev + cur;
        })
        return function(b) {
            var array = [];
            if (arguments.length === 1) {
                array[0] = a;
            } else {
                array = array.concat([].slice.call(arguments));
            }
            summary = summary_a + array.reduce(function(pre, cur) {
                return pre + cur;
            })
            return summary;
        }
    }
    sum(1, 2)(3, 4); //10
    

    这个很直白的按照柯里化的定义来写的吧,但是我是不是把它写的有点复杂了。。。改进之:

    var curry = function(fn) {
        var arr = [];
        return function() {
            if (arguments.length === 0) {
                return fn.apply(null, arr);
            } else {
                arr = arr.concat([].slice.call(arguments));
            }
        }
    }
    var sum = curry(function() {
        var summary = 0;
        for (var i = 0, len = arguments.length; i < len; i++) {
            summary += arguments[i];
        }
        return summary;
    })
    sum(1)
    sum(2,3)
    sum(4,5,6)//中间过程可以接受任意参数,任意步
    sum()//21,此时才输出结果
    

    写成这样,应该可以看出柯里化的部分优点了,在实际中我们很可能就是得到一点数据,然后计算它,再得到一些数据,那就再加上他们,这样处理起来是不是很符合逻辑了呢?再进一步观察,通过柯里化传入一个函数,我们还可以对一批数据需要做不同处理时就因地制宜的传入响应的处理函数,就像适配器模式,提高了代码的适用性,有没有~

    比如我还要计算所有数组的乘积,就只需要添加如下方法

    var mul = curry(function() {
        var product = 1;
        for (var i = 0, len = arguments.length; i < len; i++) {
            product *= arguments[i];
        }
        return product;
    })
    

    大致就是就是这个样子了~当然了,既然有柯里化,就会有反柯里化了,详情可以戳这里

    最后,大多数人(当然包括了我)并没有正确区分局部应用与柯里化,因为他们看起来是那么相同,想了解更多,可以参考这里

    【参考】
    http://blog.jobbole.com/77956/
    http://www.cnblogs.com/pigtail/p/3447660.html
    http://www.zhangxinxu.com/wordpress/2013/02/js-currying/

    相关文章

      网友评论

          本文标题:函数柯里化

          本文链接:https://www.haomeiwen.com/subject/iggwdttx.html