【问题标题】:Curried javascript sum function.咖喱 javascript sum 函数。
【发布时间】:2018-08-22 01:27:14
【问题描述】:

我遇到了这个有趣的问题。编写一个javascript函数,通过多次调用同一个函数,返回传递给它的所有参数的总和。

以下是函数的调用方式 -

sum(1, 2, 3, 4);
sum(1, 2)(3, 4);
sum(1, 2)(3)(4);
sum(1, 2, 3)(4);
sum(1)(2, 3, 4);

上面的所有调用都应该工作并返回 10。

这是我到目前为止所写的内容,但它只适用于前两个函数调用sum(1, 2, 3, 4)sum(1, 2)(3, 4),其余的都在床上。

const arr = [];

function sum(...args) {
  if (args.length === 4) {
    return args.reduce((acc, curr) => {
      return (acc = acc + curr);
    }, 0);
  } else {
    arr.push(...args);
    return function(...args) {
      arr.push(...args);
      return sum(...arr);
    };
  }
}

请有人帮帮我,这让我发疯了。

谢谢!

【问题讨论】:

  • 允许任意数量的调用会有问题,因为要使链接工作,您需要返回一个函数。但在某些时候,您需要返回一个带有最终结果的数字。
  • 这只能使用特定数量的参数(在本例中为 4)。

标签: javascript recursion closures


【解决方案1】:

你已经很接近了。这是使用.bind 方法返回一个函数的绝佳机会,如果您还没有得到至少四个参数,该函数将捕获第一个参数。

比如:

function sum(...args) {
  if (args.length >= 4) {
    return args.reduce((acc, curr) => {
      return (acc = acc + curr);
    }, 0);
  } else {
    // Bind the arguments you have to this function, and return it:
    return sum.bind(null, ...args)
  }
}

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

最后,我会更改条件以检查 >= 4,这样传递的次数就不会超过此值,而不会导致您永远咖喱。

【讨论】:

  • 没错,或者更准确地说,它需要至少四个
  • 太棒了!非常感谢!快速提问——这段代码如何保留先前调用的参数?意思是,在 sum(1,2)(3,4) 的情况下,第二个函数调用如何从第一个函数调用中获取参数?抱歉,如果这是一个愚蠢的问题。
  • 排序“至少四个”,例如这是一个错误:sum(1, 2)(3, 4)(5, 6)
  • @PowPowPow 这就是 .bind 方法的用武之地。使用 .bind 会返回一个新函数,当调用该函数时,它会自动在传递给新函数的任何参数之前传递给 @ 987654329@。 Here are the docs for bind 解释得更好一点。
【解决方案2】:

Currying 具有特定且已定义的行为,由于未定义的数量,它不能与可变参数函数很好地混合。但是,在您的特定问题中,您指定了一个元数(例如,4),因此可以知道何时返回结果

const curryN = (n, f, ...xs) =>
  (...ys) =>
    ys.length >= n
      ? f (...xs, ...ys)
      : curryN (n - ys.length, f, ...xs, ...ys)
      
const add = (...numbers) =>
  numbers.reduce ((a, b) => a + b, 0)
  
const curryAdd =
  curryN (4, add)
  
console.log
  ( curryAdd (1) (2) (3) (4) // 10
  , curryAdd (1, 2) (3, 4)   // 10
  , curryAdd (1, 2, 3) (4)   // 10
  , curryAdd (1) (2, 3, 4)   // 10
  , curryAdd (1, 2, 3, 4)    // 10
  )

虽然这是一种设计程序的脆弱方式,但它甚至不是 true currying,每个应用程序只接受一个参数。部分应用更好,因为它生成的程序具有更可靠的行为

const partial = (f, ...xs) =>
  (...ys) =>
    f (...xs, ...ys)
    
const add = (...numbers) =>
  numbers.reduce ((a, b) => a + b, 0)
  
console.log
  ( partial (add, 1) (2, 3, 4) // 10
  , partial (add, 1, 2) (3, 4) // 10
  , partial (add, 1, 2, 3) (4) // 10
  )

请阅读此related answer 以获得更多信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-06
    • 1970-01-01
    • 2018-11-09
    • 1970-01-01
    • 2022-01-02
    • 2011-04-21
    相关资源
    最近更新 更多