Estoy aprendiendo en este momento curry en js, y particularmente cómo crear una función curry genérica. Encontré un ejemplo como este:
function curry(fn) { return function curried(...args) { console.log(args) if (args.length < fn.length) { return curried.bind(null, ...args); } return fn.apply(null, args); }; }Esto funciona, y cuando le doy a esta función de curry una función con 3 argumentos como:
function add (x, y, z) {return x + y + z;} var addCurried = curry(add);y luego lo llamo así:
console.log(addCurried(1)(2)(3));entonces obtengo 4 registros:
[1]
[1,2]
[1,2,3]
6
Entiendo que cada vez que se llama a addCurried, agradecemos a "curried.bind" que obtenga una nueva función, que recursivamente llama a la función curried, y esto a su vez devuelve una nueva función y así sucesivamente. Por eso tenemos 3 llamadas para 3 argumentos. ¿Qué no puedo entender cómo el argumento "args" en la función curry interna sigue aumentando en elementos? No hacemos ningún empuje a la matriz "args". Por cierto, sin el operador resto, la misma función de curry:
function curry(fn){ return function curried() { var args = Array.prototype.slice.call(arguments); console.log(args); if (args.length < fn.length) { return function (a) { var newArgs = [].concat(args, a); return curried.apply(null, newArgs); } } return fn.apply(null, args); } }me queda completamente claro, porque hacemos "var newArgs = [].concat(args, a);" y guarde/empuje los argumentos manualmente en una matriz. Es por eso que cada vez que llamamos a la función curry interna, obtenemos un argumento más y nuestros "argumentos" siguen aumentando.
Entonces, mi pregunta es: ¿cómo en la versión del operador de descanso del argumento genérico de la función de curry "args" obtiene sus nuevos elementos? ¿Qué está pasando?
Cuando pasa argumentos para enlazar a través de curried.bind(null, ...args) la nueva función obtiene ...args como parámetros antepuestos a cualquier argumento que se le pase.
arg1, arg2, ...argN Optional Arguments to prepend to arguments provided to the bound function when invoking func.
function foo(...args) { return args; } console.log(foo(1)); // [1] // prepends 2 to args const bar = foo.bind(null, 2); console.log(bar(1)); // [2, 1] // prepends 3 to args, after the already-bound 2 const baz = bar.bind(null, 3); console.log(baz(1)); // [2, 3, 1];