Lesson 70 of 80
Currying always breaks a function into one-argument steps. Partial application just locks in some arguments now and leaves the rest for later — in one call, not a chain.
12 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
This topic is about judgment and practical tradeoffs more than a single right answer — a mock interview is the better way to test yourself on it.
Be interviewed on this →Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
This track already has a lesson on currying — go read it if you haven't, because this one assumes you know what add(1)(2)(3) is doing and builds on it rather than repeating it. The two ideas get confused constantly because they solve overlapping problems ("pre-fill some arguments, use the function later"), but they're structurally different, and interviewers ask this specifically to catch people who've memorized the word "currying" without noticing there's a second, more commonly used pattern next to it.
Currying always reshapes a function into a fixed chain of one-argument calls: f(a, b, c) becomes f(a)(b)(c), no exceptions, no fewer steps. Partial application takes any function and, in a single call, locks in some of its arguments up front — returning a new function that takes the rest, however many that is, in one remaining call rather than a chain of them.
// Partial application: fix some arguments now, take the rest later, in one call.
function partial(fn, ...fixedArgs) {
return (...remainingArgs) => fn(...fixedArgs, ...remainingArgs);
}
function add3(a, b, c) {
return a + b + c;
}
const addToTen = partial(add3, 10); // locks in `a`
addToTen(2, 3); // 15 — b and c both arrive in ONE call
const addToTenAndFive = partial(add3, 10, 5); // locks in `a` and `b`
addToTenAndFive(3); // 18 — only `c` remains
Compare that to the curried version from the currying lesson: curry(add3)(10)(2)(3) forces every argument through its own call, always three calls for a three-argument function, no matter how many you'd like to supply at once. partial(add3, 10) supplies as many or as few as you want in that first call, and whatever's left arrives together in the next one. Currying is rigid by design — one argument per step, always. Partial application is flexible about the split.
curry typically needs to know how many arguments to expect (often via fn.length) to know when to finally invoke the underlying function. partial doesn't — it just calls fn immediately with whatever arguments it's been handed across both calls, arity be damned.Exactly like currying, partial's returned function is a closure over fixedArgs — same mechanism, different shape of what gets remembered and when the underlying function finally gets called. If closures make sense, the only new thing here is the shape of the split, not a new capability of the language.