2

最近我在hackerrank中遇到了一个问题,它必须计算乘法运算并且必须返回答案。例如

function multiply(a,b) {
     return a*b;
}

现在这是函数可能以不同方式调用的问题,例如

multiply(4,5);
multiply(4)(5);
multiply(4)(5)(6);

我知道我们必须关闭第二个方法,即乘法(4)(5)。我为此编写了代码

function multiply(a,b) {
  return function(b) {
    return a*b;
  }
}

现在,如果使用 3 个参数 multiply(4)(5)(6) 调用了它的 multiply 函数会怎样。我如何确定该函数是如何被调用的,以及如何为所有输入编写一个通用解决方案。

任何帮助表示赞赏。谢谢

4

3 回答 3

3

要拥有无限的调用链,您需要一些 js 技巧:

function multiply(...args){
  //make the chain endless through using some recursive like stuff:
  const func = (...args2) => multiply(...args,...args2);
  //the chains endpoint:
  func.valueOf = function(){
     return args.reduce((a,b) => a*b);
  };
  return func;
}

这种变量柯里化的问题在于它是无限的,所以(通常)没有办法结束它。

multiply(1) // func :/

然而,在 javascript 中,可以将方法分配给函数,因此我们可以很容易地调用方法而不是函数来结束链:

multiply(1)(2)(3).valueOf()

所以你可以简单地做:

 console.log(
  +multiply(1,2,3)(4)(5),
  +multiply(1,2)
);

+ 等于valueOf,因此是结束链所必需的,但是这个对valueOf的调用是由 javascript 中的许多操作推断出来的(所有数学操作,如 - * /)。

于 2017-11-14T13:38:47.073 回答
1

这种方法的问题是返回值的模糊性。它必须同时是一个NumberAND a function

由于valueOf()您可以模拟该行为的方法,但我很少建议在生产中使用它。

const wrap = (accumulator, value) => {
  let fn = (...args) => args.length? wrap(accumulator, args.reduce(accumulator, value)): fn;
  fn.valueOf = () => value;
  return fn;
}

let mul = wrap((a,b) => a*b, 1);

console.log(+mul(4,5));
console.log(+mul(4,5)(6));
console.log(mul(4,5) * 6);
console.log(+mul(4)(5,6)(7)(8,9)()(10));

//or maybe a different operation?
let add = wrap((a,b) => a+b, 0);

console.log(+add(1,2,3,4,5));
.as-console-wrapper{top:0;max-height:100%!important;}

这种方法的缺点是,它变得非常灵活(并且模棱两可),它几乎没有用,因为很难掌握在内联的某个地方使用它会得到什么结果。如果您将某些函数输入到进行类型检查怎么办?那你就麻烦了。

于 2017-11-14T13:41:53.953 回答
0

你已经接近了,你正在尝试做的事情叫做currying,一种利用闭包的技术。

在这种情况下,您的函数一次只能接受一个参数:

function multiply(a) {
    return function(b) {
        return a * b;
    }
}

现在你可以说

function multiplyBy5 = multiply(5);
console.log(multiplyBy5(4)); //would log 20

如果您只期望最多 3 个参数,您可以这样做:

function multiply(a) {
    return function(b) {
        return function(c) {
            c = c || 1;
            return a * b * c;
        }
    }
}

这使得 c 成为可选参数。您可以通过调用该函数

multiply(4)(5)()

//or

multiply(4)(5)(6)
于 2017-11-14T13:25:36.603 回答