函数柯里化

最近看到这么一个题目

请写一个乘法函数multiply,满足multiply(x)(y)(z);的调用方式,并输出运算结果,如下面实例所示(注:最后一个无参数输入时代表结束);
console.log(multiply(2)(3)(4)()); // output: 24
console.log(multiply(4)(3)()); // output: 12

这一个感觉思路简单,但是实现起来会有很多细节的题目。

可以用闭包存储每一步的参数,然后参数为空的时候,返回这些参数的乘机。

也可以把每次的乘机计算出来,然后在参数为空的时候返回值。

其实直觉上我开始认为可以构造一个复合函数,类似 (x) => nfn(x), 但是这种符合函数经过两次执行后就会变得不可以再执行。根本原因应该是每次返回的fn都应该是一个function, 而 nfn(x)这种的值不可能再是一个function。

答案1:

function multiply(n) {
    const nums = []
    function _multiply(n) {
        if (n === undefined) {
            return nums.reduce((pre, value) => {
                return pre * value
            })
        } else {
            nums.push(n)
        }
        return _multiply
    }
    return _multiply(n)
}
复制代码

答案2:

function multiply(n) {
  return (function _multiply(...args) {
    return function(...args2) {
      if (args2.length === 0) {
        return args.reduce((prev, value) => {
          return prev * value
        })
      }
      return _multiply(...args, ...args2)
    }
  })(n)
}
复制代码

引申一下,这个题目是想做什么呢,原来这是function curry,但是因为是题目所以有点小区别。

lodash 实现的 curry

var abc = function(a, b, c) {
  return [a, b, c];
};
 
var curried = _.curry(abc);
 
curried(1)(2)(3);
复制代码

lodash.com/docs/4.17.1…

有时间看看lodash源码会对各种概念有更深入的理解。

另一篇介绍function curry的文章是:
zh.javascript.info/currying-pa…

给出的答案是:

function curry(func) {
  return function curried(...args) {
    if (args.length >= func.length) {
      return func.apply(this, args);
    } else {
      return function(...args2) {
        return curried.apply(this, args.concat(args2));
      }
    }
  };
}

function sum(a, b, c) {
  return a + b + c;
}

let curriedSum = curry(sum);

alert( curriedSum(1, 2, 3) ); // 6,仍然可以被正常调用
alert( curriedSum(1)(2,3) ); // 6,对第一个参数的柯里化
alert( curriedSum(1)(2)(3) ); // 6,全柯里化

复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享