Currying transforms a function that takes several arguments into a chain of functions that each take exactly one. A function add(a, b, c) becomes add(a)(b)(c) — call it with the first argument and you get back a new function waiting for the second, call that with the second and you get one waiting for the third. It is a specific, mechanical transformation, and it only exists because the underlying language can treat functions as ordinary values that get returned and passed around like anything else.
What changed in 2026
- Utility libraries still carry the load in most languages. JavaScript and Python do not curry automatically, and that has not changed —
curry helpers from small utility libraries, or a short hand-written wrapper, remain the standard way to get curried behavior.
- It shows up more in configuration and dependency-injection patterns. Beyond classic functional-pipeline use, more codebases now use curry-like patterns to pre-configure functions with shared settings (a logger, a base URL, a tenant ID) before handing them off to the rest of the app.
- Type systems make curried signatures easier to follow. Editors that infer and display the type of each step in a curried chain have reduced one of the classic complaints about currying: that the intermediate function signatures were hard to read.
The definition, with real code
// A small, general curry helper
const curry = (fn) => (...args) =>
args.length >= fn.length
? fn(...args)
: (...more) => curry(fn)(...args, ...more);
function addThree(a, b, c) { return a + b + c; }
const curriedAdd = curry(addThree);
curriedAdd(1)(2)(3); // 6
curriedAdd(1, 2)(3); // 6 — most curry helpers also allow grouping arguments
curriedAdd(1)(2, 3); // 6
Each call either has enough arguments to run the original function, or returns a new function that remembers what it already has and waits for the rest. This pattern depends entirely on higher-order functions — specifically, on a function's ability to return another function.
Currying vs partial application
The two get used interchangeably in casual conversation, but they are not quite the same thing. Currying always produces a chain of one-argument functions. Partial application fixes some number of arguments — any number — and returns a normal function for whatever is left, without requiring a strict one-at-a-time chain.
// Partial application: fix one argument, call normally with the rest
const addTax = (rate, price) => price + price * rate;
const addSalesTax = addTax.bind(null, 0.08);
addSalesTax(100); // 108
| Aspect |
Currying |
Partial application |
| Structure |
Chain of one-argument functions |
Fixes some arguments, returns a function for the rest |
| Arguments accepted per call |
Always exactly one |
Any number |
| Needs a full transform upfront |
Yes, typically via a curry helper |
No — .bind or a small wrapper is enough |
| Typical use |
Building composable, chained pipelines |
Creating one reusable, pre-configured variant |
A fully curried function naturally supports partial application as a side effect. The reverse is not true — partial application does not require the function to be curried at all.
A practical use: reusable, pre-configured functions
const curriedMultiply = curry((taxRate, discount, price) =>
price * (1 + taxRate) * (1 - discount)
);
const withStandardTax = curriedMultiply(0.08);
const finalPrice = withStandardTax(0.10)(49.99); // tax fixed, discount and price vary
withStandardTax is a genuinely reusable function now — every call site that needs the standard tax rate applied no longer has to repeat it, and cannot accidentally pass it in the wrong order.
Common mistakes
Currying a function that is always called with every argument at once. If no call site ever benefits from a partially applied version, currying adds a layer of indirection that only makes the code harder to step through in a debugger.
Forgetting argument order matters a lot more once curried. Put the arguments most likely to be fixed early (config, rates) first, and the ones that vary per call last — reversing that order defeats the point.
Assuming currying is automatic in every language. It is default behavior in a small number of languages built around it from the start. In most mainstream languages, it is something you opt into with a helper.
FAQ
Is currying the same as partial application?
No. They overlap in effect but differ in structure — currying is always a chain of one-argument functions; partial application can fix any number of arguments in a single step.
Do I need a library to curry functions in JavaScript?
Not strictly. A small hand-written helper like the one above covers most needs, though established utility libraries handle edge cases like variable-length argument lists more robustly.
Does currying hurt performance?
There is a small overhead from the extra function calls and closures involved. It rarely matters outside genuinely hot code paths — measure before treating it as a reason to avoid the pattern.
Is currying only useful in functional programming?
Mostly, but not exclusively. Pre-configuring a function with shared settings — a base URL, a fixed tenant ID — is a currying-adjacent pattern that shows up in ordinary object-oriented codebases too.
Where to go next