Reputation: 93
Driver code
const join = (a, b, c) => {
return `${a}_${b}_${c}`
}
const curriedJoin = curry(join)
curriedJoin(1)(2)(3)
Implementation
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) return fn(...args)
return function(...nextArgs) {
return curried(...args, ...nextArgs)
}
}
}
I'm having trouble understanding this implementation of a curried function in JavaScript, specifically the recursive case.
I think that curried
is returning an anonymous function that expects some arguments, and wraps another call of curried
passing the last call and current call's combined arguments.
I don't understand how on the next call of curry
, as in curriedJoin(2)
, the execution jumps to the wrapped function's return curried(...args, ...nextArgs)
line. Why does the execution not run through the function line by line rather than "remembering" to call this anonymous function?
I have a vague understanding of closures and I understand that the execution context is alive after the function returns - I think this is where my confusion lies.
Upvotes: 1
Views: 121
Reputation: 29314
I don't understand how on the next call of curry, as in curriedJoin(2), the execution jumps to the wrapped function's return curried(...args, ...nextArgs) line. Why does the execution not run through the function line by line rather than "remembering" to call this anonymous function?
That is because only the first call, i.e. curriedJoin(1)
, calls the curried
function directly. Calls after this, i.e. curriedJoin(1)(2)
, call the function returned by the curried
function.
As far as closures are concerned, closure is just a function saving a reference to the scope in which it is created. Example, function created in global scope has a reference to the global scope; similarly, curried
function has a reference to the local scope of curry
function.
It is this reference to the outer scope that allows a function to look for declarations in the outer scope that are not defined in its local scope.
Upvotes: 1