HuntExams Academy logo
JavaScriptAdvanced#functions

What is currying?

Answer

Transforming a multi-argument function into a chain of single-argument functions, which enables partial application and reusable specialised helpers.

Example

const mul = a => b => a * b;
const double = mul(2);
double(5); // 10

Detailed explanation

Currying transforms a function that accepts multiple arguments into a sequence of functions, each accepting one argument. Instead of calling multiply(a, b), you call its curried equivalent as multiply(a)(b). For example, const mul = a => b => a * b; defines a function that receives a and returns another function expecting b. Calling mul(2)(5) returns 10. Currying changes how arguments are supplied, not the intended calculation, and is a functional-programming technique rather than special JavaScript syntax.

Under the hood, this example relies on closures. When mul(2) executes, it returns the inner function b => a * b. That function retains access to the lexical binding of a from that particular invocation, even after the outer call finishes. Therefore, const double = mul(2); creates a reusable function with the first argument already supplied, and double(5) evaluates to 10. A separate call, such as const triple = mul(3);, creates a function associated with a different binding. The final multiplication happens only when the second argument arrives.

Currying matters because it supports partial application: supplying some arguments now and leaving the rest for later. However, the terms are not interchangeable. Currying specifically produces a chain of single-argument functions; partial application fixes some arguments without requiring that structure. For instance, const double = b => multiply(2, b); partially applies an ordinary two-argument function without converting multiply itself. Curried APIs commonly place stable configuration first and frequently changing data last, making specialised validators, formatters, and calculation helpers convenient to reuse.

Interviewers usually expect you to explain the transformation, trace the returned functions, and distinguish currying from partial application. JavaScript does not automatically curry ordinary functions; you write the nested functions or use a utility. A generic utility must decide when enough arguments have arrived, often using function.length, which has limitations with default and rest parameters. Currying also does not imply memoisation: repeated calls still perform the calculation unless caching is separately implemented.

Key points to remember

  • Currying converts f(a, b, c) into an equivalent callable chain f(a)(b)(c).
  • Intermediate calls return functions; the final call produces the result.
  • Closures let returned functions access arguments supplied in earlier calls.
  • Currying enables partial application, but partial application does not require currying.
  • Put stable configuration before changing data when designing reusable curried helpers.

Common mistakes candidates make

  • Calling mul(2, 5) when mul expects curried calls; it returns a function rather than 10 because the extra argument is unused.
  • Describing every function with pre-filled arguments as curried, confusing currying with partial application.
  • Assuming currying caches results or automatically improves performance.

Likely follow-up questions

How would you manually curry a three-argument function?

Write const add = a => b => c => a + b + c;. Then add(1)(2)(3) returns 6, while add(1)(2) returns a function waiting for c.

Can bind() be used for currying?

bind() directly supports partial application by fixing leading arguments, rather than automatically creating a single-argument chain. For function multiply(a, b) { return a * b; }, multiply.bind(null, 2) creates a doubling function.

Why can function.length be unreliable in a generic curry utility?

function.length counts parameters before the first default parameter and excludes rest parameters, so it may not represent the number of arguments the calculation needs. A curry utility can accept an explicit arity to make the stopping condition clear.

Interview tip: Start with f(a, b) becoming f(a)(b), demonstrate double = mul(2), and explain the closure before distinguishing partial application.

Related Interview Questions

1
JavaScriptIntermediate#functions

What is a higher-order function?

Open
2
JavaScriptAdvanced#performance#functions

What is memoization?

Open
3
JavaScriptBeginner#browser#storage

What are localStorage, sessionStorage and cookies?

Open