简体   繁体   中英

Curried javascript sum function.

I came across this interesting problem. Write a javascript function that returns sum of all the arguments passed to it, through multiple calls to that same function.

Here are the ways function can be called -

 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);

All the calls above should work and return 10.

Here's what I have written so far, but it only works for first two function calls sum(1, 2, 3, 4) and sum(1, 2)(3, 4) and shits the bed for rest of it.

 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); }; } }

Someone please help me, this is driving me nuts.

Thanks!

You're pretty close. This is a perfect opportunity to use the .bind method to return a function that captures the first arguments if you haven't yet been given at least four.

So something like:

 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));

Finally, I'd change the condition to check for >= 4 so that passing more than that doesn't result in a case where you'll curry forever.

Currying has a specific and defined behavior that doesn't mix well with variadic functions due to the undefined arity. However in your particular problem you specify an arity (for example, 4) so its possible to know when to return a result

 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 )

This is a fragile way to design your program though, and it's not even true currying, which only accepts 1 argument per application. Partial application is better because it produces a program with a much more reliable behavior

 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 )

Please read this related answer for additional insight.

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.

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