Currying
- Pronunciation
- KUR-ee-ing
In short
Currying turns a function that takes several arguments into a chain of functions that each take one argument, so the arguments can be supplied one at a time.
What is currying?
Currying rewrites a function of several arguments as a series of functions of one argument each. Instead of add(2, 3), a curried add is called as add(2)(3): the first call takes 2 and returns a new function that waits for the next number. The technique is named after the logician Haskell Curry, although Moses Schönfinkel had described the same idea in 1924.
It works through closures: each returned function remembers the arguments given so far, and the last one runs the real computation. In Haskell, OCaml and F#, every function is curried automatically, so calling a function with fewer arguments than it expects simply returns a function waiting for the rest. In JavaScript or Python you write it by hand with nested functions, or use a helper such as curry from Lodash or Ramda.
Currying makes it easy to build specialized functions from general ones. A curried log(level)(message) gives you log("warn") to reuse everywhere, and [1, 2, 3].map(add(10)) adds ten to every item without writing a new function. It is like a coffee machine that asks for one choice per screen: once you have picked the size, it is set up and waits only for the drink.
Currying is often mixed up with partial application. Partial application fixes some arguments of a function and returns a function that takes the rest all at once, as add.bind(null, 5) in JavaScript or functools.partial in Python do. Currying always produces a chain of one-argument functions, which in turn makes partial application trivial: calling a curried function with only its first argument is a partial application.
Key takeaways
- Currying turns
f(a, b, c)intof(a)(b)(c). - Each returned function remembers the earlier arguments through a closure.
- Haskell, OCaml and F# curry every function automatically.
- It makes it easy to create specialized functions, such as
addTenfromadd. - Partial application fixes some arguments at once; currying always takes one at a time.
Example
// A regular function takes both arguments at once
const add = (a, b) => a + b;
// The curried version takes one argument and returns a function for the next
const curriedAdd = (a) => (b) => a + b;
curriedAdd(2)(3); // 5
const addTen = curriedAdd(10); // the first argument is now fixed
[1, 2, 3].map(addTen); // [11, 12, 13]
// Partial application without currying: fix the first argument with bind
const addFive = add.bind(null, 5);
addFive(1); // 6Readers ask
What is the difference between currying and partial application?
Currying converts a function into a chain of one-argument functions. Partial application takes a function, fixes some of its arguments and returns a function of the remaining ones. Currying makes partial application easy, but they are different transformations.
Why is it called currying?
It is named after Haskell Curry, an American logician who used the idea extensively; the Haskell programming language is named after him too. Moses Schönfinkel described it earlier, so it is occasionally called schönfinkeling.
When is currying useful in JavaScript?
Mostly with higher-order functions and pipelines, where a function has to be configured first and called later, such as an event handler that needs an ID or a map callback that needs a setting. In everyday code a plain arrow function often reads more clearly, so use currying where it really makes the code shorter.
See also
- Higher-Order FunctionProgramming Fundamentals, p. 30A higher-order function is a function that takes another function as an argument, returns a function, or both, so behavior can be passed around like data.
- ClosureProgramming Fundamentals, p. 11A closure is a function that remembers the variables from the scope where it was created, so it can keep using them even after the outer function has returned.
- Functional ProgrammingProgramming Fundamentals, p. 27Functional programming is a style of building software from pure functions that avoid changing shared data, making code more predictable and easier to test.
- FunctionProgramming Fundamentals, p. 26A function is a named, reusable block of code that performs a specific task, optionally taking inputs called parameters and returning a result.
- HaskellProgramming Languages, p. 14Haskell is a purely functional, statically typed language with lazy evaluation, known for its expressive type system and mathematically precise code.
- Pure FunctionProgramming Fundamentals, p. 53A pure function always returns the same output for the same input and has no side effects, meaning it does not change anything outside itself.
Sources
Spotted a mistake or something missing on this page?Suggest an edit