1

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.

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your answer. If I understand correctly - the initial call calls curried, subsequent calls call the wrapped function which accepts new args, and then calls and returns curried with the last call's arguments and the current call's arguments concatenated. Then we recurse until the base case is reached. And I think the closure here is useful as we have access to the previous call's arguments from the scope of curried. Do you know of any resources/examples for similar types of problems? Not currying, butthe calling a function returned by a function part.
This article about closures might help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.