动态currying,以及如何在JavaScript变量中保存函数和值

时间:2016-05-29 20:16:58

标签: javascript currying

我正在学习JavaScript,最近我遇到了practice problem,要求我构建一个可以创建输出的函数,如下所示:

var threeSum= sum(3);
threeSum //3
threeSum(4) //7
threeSum(4)(3) //10
threeSum(4)(3)(7) //17
threeSum(4)(3)(7)()(2) //19
threeSum - 2 //1
threeSum + 2 //5

我认为涉及到currying,我认为我已经基本掌握了currying如何以简单的形式工作

a=>b=>c=> a+b+c

但我不知道如何创建一个能够处理不确定数量的输入的curried函数,也不知道如何使它成为一个可以作为值和函数的变量。

任何见解都表示赞赏!我只需要朝着正确的方向努力 - 此时我甚至不知道我在寻找什么。

2 个答案:

答案 0 :(得分:4)

这里的技巧是你需要定义valueOf,它允许javascript将对象(如函数)解释为值:



var valueAndCallable = function(x) {
    var res = function(a) { return a + x };
    res.valueOf = function() { return x; };
    return res;
};

var v = valueAndCallable(1)
console.log(v);      // function ... -
console.log(+v);     // 1 - calls .valueOf()
console.log(1 + v);  // 2 - calls .valueOf()
console.log(v(3));   // 4




对于currying,您只想让res()也返回valueAndCallable

答案 1 :(得分:1)

如评论中所述,您无法定义一个同时充当数字和函数的变量。

要理解可变参数函数,您必须明确地传递arity:

const curryN = n => f => {
  let next = (m, acc) => x => m > 1 ? next(m - 1, acc.concat([x])) : f(...acc, x);
  return next(n, []);
};

const sum = (...args) => args.reduce((acc, x) => acc + x, 0);

sum(1, 2, 3, 4, 5); // 15
curryN(5)(sum)(1)(2)(3)(4)(5); // 15

let sum3 = curryN(3)(sum);
sum3(1)(2)(3); // 6

let sum5plusX = curryN(2)(sum)(5);
sum5plusX(6); // 11

我建议不要使用可变参数函数。请改用Array.reduce。这是一个关于currying的有趣教程。这是一个深入的话题。