Tengo una prueba donde necesito implementar una función de alto orden llamada sum en este caso que cumple con los siguientes requisitos:
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: -> 7Hice una función para obtener el curry infinito con recursividad, pero estoy un poco perdido con la función de devolución de llamada.
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)()) -> 7Utilice un cierre para acumular la suma. Una función interna llamará a la devolución de llamada con la suma cuando detecte que el argumento es una función. De lo contrario, se devolverá solo después de adaptar la suma:
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 Si no se pretende que la función mantenga el estado, puede usar this argumento para pasar el 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 Aquí se recomienda el modo estricto, pero también funcionará en el modo descuidado. En ese caso, this argumento se encuadra y se desencuadra nuevamente.
Para simplificar, puede tener una función auxiliar que acepte dos argumentos. El primer argumento es un número. El segundo argumento sería un número o función y, según el tipo, haría cosas diferentes:
De esta manera, puede configurar una cadena continua de ejecución curry que finaliza cuando se pasa una función como argumento.
La función sum() real puede usar el asistente e inicializar el inicio de la cadena al establecer el primer argumento en 0 , el elemento neutral para la operación de suma:
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 Para simplificar, la función helper() está currada.
Aquí hay una versión más concisa:
sum() ha sido eta-reducida. 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