使用动态参数进行递归

时间:2016-07-28 11:56:08

标签: javascript recursion

这是一个我尚未弄清楚的面试问题。请考虑以下事项:

function recurse(a) {
    return function(b) {
        console.log(a + b);
    }
}

//This will log '5' in the console
recurse(2)(3);

现在我被要求编写一个函数,该函数将采用n个参数并通过记录参数值的最终总和以相同的方式工作。含义:

//This should log '13'
recurse(2)(3)(1)(7)

如何编写这样的函数?我已经尝试过在递归,动态参数等方面进行思考。但是还没有能够写下任何具体的内容。

3 个答案:

答案 0 :(得分:6)

您可以返回该功能并实施toStringvalueOf方法。

function recurse(x) {
    var sum = x;  

    function f(y) { 
        sum += y;
        return f;
    }; 
    f.toString = function () { return sum; }; // for expecting string, 1st log
    f.valueOf = function () { return sum; };  // for expecting number, 2nd log

    return f;
}

console.log(recurse(2)(3)(4));
console.log(recurse(2)(3) + recurse(4)(5));
console.log(recurse(2)(40) == 42);  // converts to expected type Number
console.log(recurse(2)(40) === 42); // checks type Function

答案 1 :(得分:3)

这是我能想到的最简单的版本:

function add (a) {
  return function (b) {
    return b == null ? a : add(a+b);
  }
}

console.log( 
  add(2)(3)() 
);
console.log(
  add(10)(100)(1000)(4)() 
);

在es6中,它很紧凑!

let add = a => b => b == null ? a : add(a+b);

注意

问题的问题在于功能可以 返回Function a Number。以下代码:

let result = add(2)(3);

相当于:

/*1*/ let partialResult = add(2);
/*2*/ let result = partialResult(3);

在第1行中,add不知道是否使用最后一个参数调用它!换句话说,它不知道partialResult应该是一个数字,还是一个将用另一个参数调用的函数。

Nina Scholz为您提供了一个解决方案,其中partialResult在处理为primitive时会像数字一样运行,并且像函数一样调用时就像函数一样。在我的解决方案中,partialResult总是像函数一样,并且在没有参数的情况下调用时返回一个总和。

第一种方法需要一种特定于语言的机制,以便在某些条件下“表现得像一个数字”。如果您的采访是关于JavaScript的,那么这是最好的近似值!但是在语言不可知的背景下,你所要求的是不可能的。

答案 2 :(得分:2)

实际上 返回 并不要求递归。它应该只是 log

因为要求是 记录参数值的最终总和 ,我们可以假设记录中间求和也是完全正确的(除非它是明确禁止在完整的问题陈述中。)

所以,我想面试官会接受以下解决方案。考虑到最初的源代码,它实际上可能是他/她所期望的。

function recurse(a) {
  console.log(a);
  return function(b) {
    return recurse(a + b);
  }
}

recurse(2)(3)(5)(7)

如果您确实只想显示最后一笔总和,可以:

  1. 使用console.clear()(不是我首选的解决方案)作弊:
  2. function recurse(a) {
      console.clear();
      console.log(a);
      return function(b) {
        return recurse(a + b);
      }
    }
    
    recurse(2)(3)(5)(7)

    1. 使用clearTimeout()setTimeout()的组合。在这里,我们利用Javascript的单线程特性,这可以防止在完全评估表达式之前执行回调。
    2. var t;
      
      function recurse(a) {
        t && clearTimeout(t);
        t = setTimeout('console.log(' + a + ');', 0);
        return function(b) {
          return recurse(a + b);
        }
      }
      
      recurse(2)(3)(5)(7)