Daily-Question icon indicating copy to clipboard operation
Daily-Question copied to clipboard

【Q421】如何实现一个无限累加的 sum 函数

Open shfshanyue opened this issue 4 years ago • 9 comments

实现一个 sum 函数如下所示:

sum(1, 2, 3).valueOf() //6
sum(2, 3)(2).valueOf() //7
sum(1)(2)(3)(4).valueOf() //10
sum(2)(4, 1)(2).valueOf() //9
sum(1)(2)(3)(4)(5)(6).valueOf() // 21

追问:

如果不使用 valueOf,可直接进行计算,如下示例,应如何处理。

//=> 15
sum(1, 2, 3) + sum(4, 5)

//=> 100
sum(10) * sum(10)

shfshanyue avatar Aug 26 '20 11:08 shfshanyue

这还是字节、快手、阿里一众大厂最为偏爱的题目,实际上有一点技巧问题。

这是一个关于懒计算的函数,使用 sum 收集所有累加项,使用 valueOf 进行计算

  1. sum 返回一个函数,收集所有的累加项,使用递归实现
  2. 返回函数带有 valueOf 属性,用于统一计算

代码见 【Q421】如何实现无限累加的一个函数,方便测试与调试

function sum (...args) {
  const f = (...rest) => sum(...args, ...rest)
  f.valueOf = () => args.reduce((x, y) => x + y, 0)
  return f
}

shfshanyue avatar Aug 26 '20 11:08 shfshanyue

这是一个关于懒计算的函数,使用 sum 收集所有累加项,使用 valueOf 进行计算

  1. sum 返回一个函数,收集所有的累加项,使用递归实现
  2. 返回函数带有 valueOf 属性,用于统一计算
function sum (...args) {
  const f = (...rest) => sum(...args, ...rest)
  f.valueOf = () => args.reduce((x, y) => x + y, 0)
  return f
}

看了好多遍才理解,大佬果然是大佬。 关键点在于每次调用后返回自己所返回的东西,也就是函数f。 同时收集每次传进来的参数并做对应的操作。

haiifeng avatar Jul 21 '21 06:07 haiifeng

这算不算函数柯里化?

Mingeax avatar May 07 '22 13:05 Mingeax

这还是字节、快手、阿里一众大厂最为偏爱的题目,实际上有一点技巧问题。

这是一个关于懒计算的函数,使用 sum 收集所有累加项,使用 valueOf 进行计算

  1. sum 返回一个函数,收集所有的累加项,使用递归实现
  2. 返回函数带有 valueOf 属性,用于统一计算

代码见 【Q421】如何实现无限累加的一个函数,方便测试与调试

function sum (...args) {
  const f = (...rest) => sum(...args, ...rest)
  f.valueOf = () => args.reduce((x, y) => x + y, 0)
  return f
}

这闭包用的让人虎躯一震 太强了

Vi-jay avatar May 12 '22 03:05 Vi-jay

写一个啰嗦一点的版本供大家参考: 想法很简单:

  1. 用一个变量收集所有的参数。
  2. 返回一个带有 valueOf 属性的 function。
function sum(...args: number[]) {
  // allArgs 收集所有的 args
  let allArgs = args;

  // 返回一个 function 可以接受参数   
  function fn(...args2) {
    allArgs = allArgs.concat(args2);
    return fn;
  }
  
  // function 上有一个属性叫 valueOf
  fn.valueOf = function () {
    // valueOf 触发时才开始累加
    return allArgs.reduce((res, cur) => (res += cur));
  };
  return fn;
}

wangjs-jacky avatar Jun 10 '22 02:06 wangjs-jacky

function getNum(...args) { return args.reduce((prev, next) => { return prev + next }, 0) }

zfy171 avatar Jul 23 '22 05:07 zfy171

自己尝试写了一版,不过不是懒计算,调用一次算一次,计算的结果利用闭包缓存:

function sum(
  ...args: number[]
) {
  const value = args.reduce((pre, cur) => pre + cur, 0);

  const _sum = function (..._arg: number[]) {
    return sum.call(null, value, ..._arg);
  };

 _sum.valueOf = () => console.log(value)

 return _sum

}

kirazZ1 avatar Mar 13 '23 02:03 kirazZ1

追问:

如果不使用 valueOf,可直接进行计算,如下示例,应如何处理。

//=> 15
sum(1, 2, 3) + sum(4, 5)

//=> 100
sum(10) * sum(10)

实现这个效果:覆写 toStringSymbol.toPrimitive 即可。

function sum(...args) {
    const f = (...fArgs) => !fArgs.length ? f.toString() : sum(...args, ...fArgs)
    f.toString = () => args.reduce((cur, next) => cur + next)
    return f
}

justorez avatar Mar 22 '23 06:03 justorez

function sum(...args){
  const foo = (...rest) => sum(...args, ...rest)
  foo.toString = () => args.reduce((x, y) => x + y, 0)
  return foo
}
console.log(sum(1)(2, 3) + sum(1)) // 7
console.log(sum(10) * sum(10)) // 100

被这一波操作秀到了reduce真好用

Hazel-Lin avatar Jul 07 '23 02:07 Hazel-Lin