【问题标题】:Create a function with an undetermined number of successive calls创建一个连续调用次数不确定的函数
【发布时间】:2017-02-02 22:35:02
【问题描述】:

作为编程挑战的一部分,我们的任务是创建一个具有不确定数量的连续调用的函数。例如,假设函数只返回所提供参数的总和,它应该如下工作:

sum(4)() // 4
sum(4)(5)() // 9
sum(4)(5)(9)() // 18
sum(4)(5)(9)(1)() // 19
// etc...

通过最后允许的空函数调用作为调用结束的指示来简化问题。

我已经研究了一个解决方案,它可以完成这项工作,但在函数本身内部使用全局变量:

var sum = function (a) {
    if (!sum.init) {
        sum.total = 0;
        sum.init = true;
    }
    if (!arguments.length) {
        sum.init = false;
        return sum.total;
    }
    sum.total += a;
    return sum;
};

此解决方案有效,但使用了不理想的状态、全局变量和函数对象技巧。我的问题是,是否有办法以纯递归的方式解决问题。

附带说明,如果没有提供最后一个空调用 (),我认为问题无法解决,但如果我错了,请告诉我。

更新

CodeReview 已经回答了这个问题:https://codereview.stackexchange.com/a/153999/129579

一种不依赖全局范围且纯粹是功能性的解决方案。

【问题讨论】:

  • 这看起来像是属于 codereview 的
  • 可能值得包含链接:codereview.stackexchange.com
  • 你研究过柯里化吗?
  • 谢谢大家,我会在codereview中发布。
  • epascarello,我做到了,但我不知道函数柯里化如何解决这个问题,也许是一个线索?

标签: javascript functional-programming


【解决方案1】:

您可以像这样使用 闭包 来实现您想要的:

function sum(value){
  // the closure variable that will be accessible for all the _sum calls (initialised to 0 for every sum call).
  var result = 0;
  
  // the function that will be returned (sum will only get called once to initialize the result to 0. It's _sum which will be returned as much as possible)
  function _sum(a){
    // if we passed a parameter, then add it to result and return a new _sum
    if(typeof a != "undefined"){
      result += a;
      return _sum;
    }
    // if we didn't return the result
    else
      return result;
  }
  // of course after initializing result we need to call _sum that handle the actual summing and return whatever it returns (if value is defined, it will return another `_sum` if not it will return the value of result which will be 0 at first) from now on sum will have nothing to do with the rest of the calls (()()()... )
  return _sum(value);
}

console.log("sum() = " + sum());
console.log("sum(7)() = " + sum(7)());
console.log("sum(5)(6)(7)() = " + sum(5)(6)(7)());

// will return 0 because we call sum again
console.log("sum() = " + sum());

注意:sum(1)(7)(3)()); 将按以下顺序调用:

  1. sum 带有参数1,它将把result 初始化为0 并调用
  2. _sum 使用相同的参数 1 将其添加到 result 并返回一个新的 _sum inctance 将被调用,因此如下
  3. _sum 使用参数7 调用,添加它并返回一个新的_sum 所以新的
  4. 使用参数3 调用_sum,...生成另一个
  5. _sum 将没有参数,因此 if(typeof a != "undefined") 将失败,而此 _sum 将返回 result

实际的sum 在开始时只被调用一次来进行初始化。正如我所说,_sum 在此之后一直被束缚到最后。

【讨论】:

  • if(a) 表示0会返回结果,断链。
  • @Francis 没想到。我会更新我的答案。谢谢!
【解决方案2】:

基本上,您可以使用外部函数sum 进行初始调用,并使用初始值a 的闭包和内部函数fn,它会重复返回并且仅在arguments.length 等于零时退出.

如果提供了值 b,则变量 a 会更新并返回内部函数 fn

function sum(a) {
    return function fn(b) {
        if (!arguments.length) {
            return a;
        }
        a += b;
        return fn;
    };
}

console.log(sum(1)());
console.log(sum(1)(2)());
console.log(sum(1)(2)(3)());

编辑不带参数调用 sum

function sum(a) {
    return arguments.length ?
        function fn(b) {
            if (!arguments.length) {
                return a;
            }
            a += b;
            return fn;
        } :
        0;
}

console.log(sum());
console.log(sum(1)());
console.log(sum(1)(2)());
console.log(sum(1)(2)(3)());

【讨论】:

  • 如果他调用 sum 时不带参数怎么办:sum();
  • 请看第二种方法,它返回你的,零。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-21
  • 1970-01-01
相关资源
最近更新 更多