skip to content

In JavaScript, what is the difference between currying a function and partially applying it?

level: middleimportance: should knowfreq 55%

answer

  1. shape change versus supply step
  2. chain of calls versus one step
  3. bind pins the leading arguments
  4. arity shrinks, no chain created
  5. loose curry blurs the two

basics

~20 s

Currying turns an n-argument function into a chain of n calls that each take one argument. Partial application fixes some arguments once and hands back a function that takes the remaining ones — a single step, not a chain.

solid answer

~40 s

Currying is a *shape* transformation: `f(a, b, c)` becomes `f(a)(b)(c)`, where every call takes exactly one argument and returns another function until the last one, which returns the result. Partial application is an *application* step: you supply some of the arguments now and get back a function of smaller arity that waits for the rest. `const add3 = (a) => (b) => (c) => a + b + c` is curried; `const add5 = add.bind(null, 5)` is a partial application of a normal two-argument `add`. The built-in tool for partial application is `Function.prototype.bind`, which pins leading arguments; currying normally needs a helper you write. The confusion comes from "loose" curry helpers that also accept several arguments at once — `curried(1, 2)(3)` — which is really auto-currying plus partial application in one object.

go deeper

for a junior

Be able to show f(a)(b) returning a function at each step, and to say plainly that bind can pre-fill arguments as well as set the receiver.

for a middle

Explain that currying is a fixed one-argument-per-call shape while partial application is fixing some arguments of a normal function, and show both with real code including arity effects.

for a senior

Demonstrate judgment about argument order: currying only pays off with data-last signatures, and loose curry helpers behave surprisingly when callback APIs pass extra arguments.

for a principal

Own the API-design angle — deciding parameter order across a shared library determines whether specialisation is free or requires wrapper functions everywhere, and that decision is expensive to reverse.

## The distinction in one line Currying changes the *shape* of a function. Partial application changes *how much of it you have supplied so far*. A curried function is one whose call signature is a chain of single-argument calls; a partially applied function is the leftover of a normal function after some arguments were already fixed. ## Currying: one argument per call A function of arity three, curried by hand, is three nested single-parameter functions: ```js const add3 = (a, b, c) => a + b + c; const curriedAdd3 = (a) => (b) => (c) => a + b + c; add3(1, 2, 3); // 6 curriedAdd3(1)(2)(3); // 6 curriedAdd3(1); // a function, not a number ``` Each intermediate call returns a new function; nothing is computed until the last argument arrives. `curriedAdd3.length` is `1`, because each step declares exactly one parameter, and each intermediate value is a fresh function object — calling `curriedAdd3(1)` twice gives you two distinct functions that behave the same. ## Partial application: pin some, keep the rest Partial application starts from an ordinary multi-argument function and produces a function of smaller arity: ```js function greet(greeting, name) { return `${greeting}, ${name}!`; } const hi = greet.bind(null, 'Hi'); hi('Ada'); // "Hi, Ada!" hi.length; // 1 — one parameter still outstanding ``` `Function.prototype.bind` is the language's built-in partial application: everything after its first argument is stored and prepended to whatever you pass later. A closure does the same job without `bind`: ```js const partial = (fn, ...fixed) => (...rest) => fn(...fixed, ...rest); const hi2 = partial(greet, 'Hi'); ``` Notice there is no chain here. `hi` is not "the curried greet"; it is `greet` with one slot already filled. ## Where the two meet Calling a curried function with one argument *is* a partial application of it — that is why the terms blur. The clean way to keep them apart: currying is a property of the function's definition, partial application is something you do to a function at a call site. You can partially apply a function that was never curried (`bind`), and you can curry a function without ever partially applying it (call the whole chain in one expression). Most real-world `curry` helpers are "loose" or auto-curried: they accept any number of arguments per call and only invoke the underlying function once enough have accumulated. ```js const curried = curry(add3); curried(1)(2)(3); // 6 curried(1, 2)(3); // 6 curried(1, 2, 3); // 6 ``` Strictly, `curried(1, 2)` is currying plus partial application at once. Say so explicitly in an interview — it shows you know the difference rather than merely reciting it. ## Why anyone bothers Both exist so that configuration can be separated from data. A logging helper written argument-order "config first, data last" can be specialised once and reused: ```js const log = (level) => (msg) => console.log(`[${level}] ${msg}`); const warn = log('WARN'); warn('disk almost full'); ``` That data-last ordering is what makes curried helpers usable in pipelines without writing a wrapper arrow at every step. With arguments ordered data-first, currying gains you very little, because the piece you want to fix is the one you would have to supply first. ## Traps worth naming A curried or partially applied function is still an ordinary function that ignores no arguments: hand `curried` to a callback API that passes extra arguments and the loose helper may consider itself complete far earlier than you intended. Partial application via `bind` can only pin arguments **from the left** — there is no built-in placeholder for "skip the second parameter". And neither operation mutates or replaces the original function; both return a new function object, so the original stays callable in its normal form.

  • Is `f.bind(null, 1)` currying?
    No — it is partial application. `bind` returns a single function with one argument already fixed and the rest still expected together; it does not restructure `f` into a chain of one-argument calls. If `f` had three parameters, `f.bind(null, 1)` still takes two at once, whereas a curried `f` would take them one at a time.
  • What happens to the reported arity of a function after you partially apply it with `bind`?
    The bound function's `length` is the target's `length` minus the number of arguments you pinned, floored at zero. For `function f(a, b, c) {}`, `f.bind(null, 1).length` is `2`. Its `name` also becomes `"bound f"`, which is handy when reading stack traces full of pre-configured helpers.
  • Why does argument order matter so much when you plan to curry?
    Currying only fixes arguments from the left, so whatever you want to specialise must come first and the varying data last. A `filter(predicate)(list)` shape specialises cleanly; `filter(list, predicate)` does not, because the thing you would fix is in the wrong position and you end up writing a wrapper arrow anyway.

saying these in an interview costs you the question

  • Says currying and partial application are just two names for the same thing
  • Thinks bind can only set this and cannot pre-fill arguments
  • Claims currying modifies or replaces the original function
  • Believes each step of a curried function may take several arguments by definition
  • Says currying makes calls faster or reduces work

context