简体   繁体   English

如何使用回调 function 实现无限柯里化总和值,结果为 javascript?

[英]How to implement infinite currying sum values with a callback function with result in javascript?

I have a test where I need to implement a high order function called sum in this case that fulfills the following requirements:我有一个测试,我需要在这种情况下实现一个称为 sum 的高阶 function ,它满足以下要求:

sum(result => {console.log("-> ", result)});// -> prints: -> 0
sum(1)(result => {console.log("-> ", result)});// -> prints: -> 1
sum(1)(2)(result => {console.log("-> ", result)});// -> prints: -> 3
sum(1)(2)(4)(result => {console.log("-> ", result)});// -> prints: -> 7

I did a function in order to get the infinite currying with recursion but I'm a little bit lost with the callback func.我做了一个 function 以通过递归获得无限柯里化,但我对回调函数有点迷失了。

let sum = a => !a ? 0 : b => b ? sum(a+b) : a
console.log(sum()) -> 0
console.log(sum(1)()) -> 1
console.log(sum(1)(2)()) -> 3
console.log(sum(1)(2)(4)()) -> 7

Use a closure to accumulate the sum.使用闭包来累积总和。 An inner function will call the callback with the sum when it detects the argument is a function.当检测到参数是 function 时,内部 function 将使用总和调用回调。 Otherwise it will return itself after adapting the sum:否则它将在调整总和后返回:

 function sum(arg) { let total = 0; function inner(arg) { if (typeof arg === "function") { arg(total); } else { total += arg; return inner; } } return inner(arg); } sum(result => {console.log("-> ", result)});// -> prints: -> 0 sum(1)(result => {console.log("-> ", result)});// -> prints: -> 1 sum(1)(2)(result => {console.log("-> ", result)});// -> prints: -> 3 sum(1)(2)(4)(result => {console.log("-> ", result)});// -> prints: -> 7

If it is not intended that the function maintains state, then you can use the this argument to pass on the total:如果不打算让 function 维护 state,那么您可以使用this参数传递总数:

 "use strict"; function sum(arg) { function inner(arg) { if (typeof arg === "function") { arg(+this); } else { return inner.bind(this + arg); } } return inner.call(0, arg); } sum(result => {console.log("-> ", result)});// -> prints: -> 0 sum(1)(result => {console.log("-> ", result)});// -> prints: -> 1 sum(1)(2)(result => {console.log("-> ", result)});// -> prints: -> 3 sum(1)(2)(4)(result => {console.log("-> ", result)});// -> prints: -> 7 const foo = sum(0); foo(100)(console.log); // 100 foo(1)(console.log); // 1

Strict mode is advised here, but it will work in sloppy mode as well.这里建议使用严格模式,但它也可以在草率模式下工作。 In that case the this argument is boxed and unboxed again.在这种情况下, this参数将被装箱并再次拆箱。

For simplicity, you can have a helper function that accepts two arguments.为简单起见,您可以有一个辅助程序 function 接受两个 arguments。 The first argument is a number.第一个参数是一个数字。 The second argument would be a number or function and based on the type it would do different things:第二个参数将是一个数字或 function 并且根据类型它会做不同的事情:

  • when it is a function it will execute it and pass the first argument into it.当它是 function 时,它将执行它并将第一个参数传递给它。
  • when it is a number, it will add the two arguments together and pass that as the first argument of the helper.当它是一个数字时,它将两个 arguments 加在一起,并将其作为助手的第一个参数传递。 Next time, the first argument will contain the new total.下一次,第一个参数将包含新的总数。

This way you can set up an continual chain of curried execution that gets terminated when a function is passed as an argument.通过这种方式,您可以设置一个连续的柯里化执行链,当 function 作为参数传递时终止。

The actual sum() function can use the helper and initialise the start of the chain by setting the first argument to 0 - the neutral element for the addition operation.实际的sum() function 可以使用辅助函数并通过将第一个参数设置为0 (加法运算的中性元素)来初始化链的开始。

 const helper = total => arg => { if (typeof arg === "function") arg(total); else if (typeof arg === "number") return helper(total + arg); else throw new Error("invalid argument"); } const sum = x => helper(0)(x); sum(result => {console.log("-> ", result)});// -> prints: -> 0 sum(1)(result => {console.log("-> ", result)});// -> prints: -> 1 sum(1)(2)(result => {console.log("-> ", result)});// -> prints: -> 3 sum(1)(2)(4)(result => {console.log("-> ", result)});// -> prints: -> 7

For simplicity, the helper() function is curried.为简单起见, helper() function 是咖喱的。


Here is a more concise version:这是一个更简洁的版本:

  • assumes that only number or function will be passed in.假设只有数字或 function 将被传入。
  • The definition of sum() has been eta-reduced. sum()的定义已减少。

 const helper = total => arg => (typeof arg === "function")? arg(total): helper(total + arg); const sum = helper(0); sum(result => {console.log("-> ", result)});// -> prints: -> 0 sum(1)(result => {console.log("-> ", result)});// -> prints: -> 1 sum(1)(2)(result => {console.log("-> ", result)});// -> prints: -> 3 sum(1)(2)(4)(result => {console.log("-> ", result)});// -> prints: -> 7

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM