I have a test where I need to implement a high order function called sum in this case that fulfills the following requirements:
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.
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. 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:
"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.
For simplicity, you can have a helper function that accepts two 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:
This way you can set up an continual chain of curried execution that gets terminated when a function is passed as an argument.
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.
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.
Here is a more concise version:
sum()
has been eta-reduced. 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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.