Javascript 可变咖喱求和函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5832891/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 19:06:30  来源:igfitidea点击:

Variadic curried sum function

javascriptcurrying

提问by Yaroslav Yakovlev

I need a js sum function to work like this:

我需要一个 js sum 函数才能像这样工作:

sum(1)(2) = 3
sum(1)(2)(3) = 6
sum(1)(2)(3)(4) = 10 
etc.

I heard it can't be done. But heard that if adding +in front of sumcan be done. Like +sum(1)(2)(3)(4).
Any ideas of how to do this?

听说做不到 不过听说如果+在前面加上sum就可以了。喜欢+sum(1)(2)(3)(4)
关于如何做到这一点的任何想法?

回答by Rafael

Not sure if I understood what you want, but

不确定我是否理解你想要的,但是

function sum(n) {
  var v = function(x) {
    return sum(n + x);
  };

  v.valueOf = v.toString = function() {
    return n;
  };

  return v;
}

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

JsFiddle

提琴手

回答by yury.hrynko

This is an example of using empty brackets in the last call as a close key (from my last interview):

这是在最后一次调用中使用空括号作为关闭键的示例(来自我上次采访):

sum(1)(4)(66)(35)(3)()

总和(1)(4)(66)(35)(3)()

function sum(numberOne) {
  var count = numberOne;
  return function by(numberTwo) {
    if (numberTwo === undefined) {
      return count;
    } else {
      count += numberTwo;
      return by;
    }
  }
}
console.log(sum(1)(4)(66)(35)(3)());

回答by Brad

I'm posting this revision as its own post since I apparently don't have enough reputation yet to just leave it as a comment. This is a revision of @Rafael 's excellent solution.

我将此修订版作为自己的帖子发布,因为我显然还没有足够的声誉来将其作为评论。这是@Rafael 优秀解决方案的修订版。

function sum (n) {
    var v = x => sum (n + x);
    v.valueOf = () => n; 
    return v;
}

console.log(+sum(1)(2)(3)(4)); //10

I didn't see a reason to keep the v.toString bit, as it didn't seem necessary. If I erred in doing so, please let me know in the comments why v.toString is required (it passed my tests fine without it). Converted the rest of the anonymous functions to arrow functions for ease of reading.

我没有看到保留 v.toString 位的理由,因为它似乎没有必要。如果我这样做是错误的,请在评论中告诉我为什么需要 v.toString(没有它它通过了我的测试)。将其余的匿名函数转换为箭头函数以方便阅读。

回答by Artokun

Here is a solution that uses ES6 and toString, similar to @Vemba

这是一个使用 ES6 和 的解决方案toString,类似于@Vemba

function add(a) {
  let curry = (b) => {
    a += b
    return curry
  }
  curry.toString = () => a
  return curry
}

console.log(add(1))
console.log(add(1)(2))
console.log(add(1)(2)(3))
console.log(add(1)(2)(3)(4))

回答by user1034533

Here's a solution with a generic variadic curry function in ES6 Javascript, with the caveat that a final ()is needed to invoke the arguments:

这是一个在 ES6 Javascript 中使用通用可变参数 curry 函数的解决方案,但需要注意的()是,需要使用 final来调用参数:

const curry = (f) =>
   (...args) => args.length? curry(f.bind(0, ...args)): f();
const sum = (...values) => values.reduce((total, current) => total + current, 0)
curry(sum)(2)(2)(1)() == 5 // true

Here's another one that doesn't need (), using valueOfas in @rafael's answer. I feel like using valueOfin this way (or perhaps at all) is very confusing to people reading your code, but each to their own.

这是另一个不需要的()valueOf@rafael 的回答中使用。我觉得valueOf以这种方式(或者可能根本没有)使用会让阅读您的代码的人感到非常困惑,但每个人都有自己的。

The toStringin that answer is unnecessary. Internally, when javascript performs a type coersion it always calls valueOf()before calling toString().

toString在这个问题的答案是不必要的。在内部,当 javascript 执行类型转换时,它总是valueOf()在调用toString().


// invokes a function if it is used as a value
const autoInvoke = (f) => Object.assign(f, { valueOf: f } );

const curry = autoInvoke((f) =>
   (...args) => args.length? autoInvoke(curry(f.bind(0, ...args))): f());

const sum = (...values) => values.reduce((total, current) => total + current, 0)
curry(sum)(2)(2)(1) + 0 == 5 // true

回答by Jonas Wilms

Another slightly shorter approach:

另一种略短的方法:

 const sum = a => b => b? sum(a + b) : a;

Usable as:

可用作:

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

回答by Deepak K

New ES6 way and is concise.

新的 ES6 方式并且简洁。

You have to pass empty () at the end when you want to terminate the call and get the final value.

当你想终止调用并获得最终值时,你必须在最后传递 empty() 。

const sum= x => y => !!y ? sum(x + y) : x;

call it like this -

像这样称呼它-

sum(10)(30)(45)();

回答by shekhardtu

Might be an old question but a little extended answer

可能是一个老问题,但答案有点长

function sum() {

    var args = [];
    args.push(...arguments);

    function sumOfAllArguments() {
        return args.reduce((prev,items)=>prev + items, 0)
    }

    function v() {
        arguments && args.push(...arguments);
        return arguments.length === 0 ? sumOfAllArguments() : v;
    }

    v.valueOf = v.toString = sumOfAllArguments;

    return v;

}
        
    

        console.log(sum(2)(2)(2)()) // 6
        console.log(sum(2)(2)(2).toString()) // 6
        console.log(sum(2)(2)(2).valueOf()) // 6
        console.log(+sum(2)(2)(2)) //6
        console.log(sum(2)(2)(2)) // f 6

        console.log(sum(2,2,2)(2,2)(2)) // f 12
        console.log(sum(2)(2,2)(2)()) //  8

回答by UtkarshPramodGupta

Here's a more generic solution that would work for non-unary params as well:

这是一个更通用的解决方案,它也适用于非一元参数:

const sum = function (...args) {
  let total = args.reduce((acc, arg) => acc+arg, 0)
  function add (...args2) {
    if (args2.length) {
      total = args2.reduce((acc, arg) => acc+arg, total)
      return add
    }
    return total
  }

  return add
}

document.write( sum(1)(2)() , '<br/>') // with unary params
document.write( sum(1,2)() , '<br/>') // with binary params
document.write( sum(1)(2)(3)() , '<br/>') // with unary params
document.write( sum(1)(2,3)() , '<br/>') // with binary params
document.write( sum(1)(2)(3)(4)() , '<br/>') // with unary params
document.write( sum(1)(2,3,4)() , '<br/>') // with ternary params

回答by Aliaksandr Sushkevich

Here is another functional way using an iterative process

这是使用迭代过程的另一种功能方式

const sum = (num, acc = 0) => {
    if (!num) return acc;
    return x => sum(x, acc + num)
}

sum(1)(2)(3)()

and one-line

和单线

const sum = (num, acc = 0) => !num ? acc : x => sum(x, acc + num)

sum(1)(2)(3)()