Introduction
In our last lesson on function composition, we built powerful data processing pipelines using pipe and compose. We also hit a roadblock: these pipelines work best with unary functions (functions that take one argument). This raises a critical question: how can we incorporate functions that require multiple arguments, like replace(pattern, replacement, string), into our compositions?
This lesson provides the answer by exploring two closely related functional programming techniques: partial application and currying. Your goal is to implement partial application and currying to create specialized functions from more general ones. These techniques are the glue that allows you to transform multi-argument functions into composable, single-argument building blocks, dramatically increasing the power and flexibility of your code. For you as a software engineer, mastering these patterns unlocks a more modular and declarative programming style.
Partial Application: Pre-configuring Functions
Let's start with the more straightforward concept: partial application. It's the process of creating a new function by "pre-filling" or "locking in" some of the arguments of an existing, more general function. The "pre-filled" arguments are held in a closure, and the new function simply waits for the remaining arguments to be provided.
Imagine you have a generic function multiply(a, b). If you frequently need to double numbers, you could create a specialized double function. Partial application is the formal name for this process.
// A general, multi-argument function
function multiply(a, b) {
return a * b;
}
// A new function created by partially applying 'multiply'
// We "lock in" the 'a' argument as 2.
const double = (b) => multiply(2, b);
console.log(double(10)); // 20
Here, double is a partial application of multiply. We created a more specific function from a general one. This is a manual process that you've likely done intuitively before.
The following article uses a conversational narrative to clearly distinguish between partial application and its close cousin, currying.
The Secret Life of JavaScript: Currying vs. Partial Application
This article provides an excellent, easy-to-understand breakdown of partial application and currying.
Start by reading the first two sections: The Practical Approach: This introduces partial application using the same multiply example we just saw. The Structural Approach: This section defines currying, setting the stage for the next topic. Pay attention to the distinction between a manual preparation (partial application) and a structural transformation (currying).
Currying: A Chain of Functions
While partial application is about creating a specific new function with fewer arguments, currying is a more formal transformation. It converts a function that takes multiple arguments, like f(a, b, c), into a sequence of functions that each take only a single argument: f(a)(b)(c).
Each time you call a function in the chain, it returns another function that waits for the next argument, until all arguments are supplied and the final result is returned. This structure relies heavily on closures, where each nested function has access to the arguments passed to its parent functions.

Let's see how this looks in code with a simple sum function.
// A normal function
function sum(a, b, c) {
return a + b + c;
}
// The same function, manually curried
function curriedSum(a) {
return function(b) {
return function(c) {
return a + b + c;
};
};
}
console.log(sum(1, 2, 3)); // 6
console.log(curriedSum(1)(2)(3)); // 6
// The power of currying: creating specialized functions
const add5 = curriedSum(5);
const add5and10 = add5(10);
console.log(add5and10(20)); // 35
Notice how calling curriedSum(5) gives us back a new function, add5, which is a partial application of curriedSum. Currying makes partial application incredibly simple and is a natural fit for function composition.
To solidify your understanding, the video below provides a great walkthrough of the concept, including practical interview-style questions.
Javascript Interview Questions ( Currying ) - Output based Questions, Partial Application and more
This video from RoadsideCoder explains currying from the ground up and distinguishes it from partial application.
Watch the following segments: What is currying? to see the definition and a basic example. Why use currying? for a quick summary of its benefits. Implementing sum, which walks through the exact curriedSum function we just wrote. Currying vs. Partial Application for a clear distinction. Pay attention to the concept of "arity" (the number of arguments a function takes).
The Key Difference: An Analogy
The terms "currying" and "partial application" are often used interchangeably, but their distinction is important.
- Partial Application is a manual process. You decide which arguments to pre-fill. You could turn
f(a,b,c)intog(c)by pre-fillingaandb, or intoh(a)by pre-fillingbandc. - Currying is a structural transformation. It always turns
f(a,b,c)intof(a)(b)(c). It enforces a rigid, one-argument-at-a-time chain.
The dev.to article you read earlier offers a fantastic analogy to remember this difference.
The Secret Life of JavaScript: Currying vs. Partial Application
This analogy perfectly captures the difference in flexibility between the two concepts.
Please read the sections: The Partial Application Sandwich Maker The Curried Assembly Line The key takeaway is that partial application is like a flexible sandwich maker where you can add ingredients in any way you choose, while currying is like a rigid assembly line where each station must receive one specific ingredient in a fixed order.
Practical Application: Creating Function Factories
The "rigid assembly line" of currying is precisely what makes it so powerful for creating specialized functions. By stopping the "assembly line" at any point, you get a new, more specific function.
This example from the RoadsideCoder video demonstrates this beautifully. A generic evaluate function is curried to create specific arithmetic functions like mul.
Javascript Interview Questions ( Currying ) - Output based Questions, Partial Application and more
Watch these two practical examples of how currying is used to create specialized functions.
The evaluate function: This shows how to create a generic function that can perform different operations, and then use currying to create specialized versions like multiply. DOM manipulation: This real-world example demonstrates how you can create a specialized updateHeader function from a generic updateElementText function, avoiding repeated calls to document.querySelector.
Automating with a curry Higher-Order Function
Manually currying every function is tedious. As with compose and pipe, we can create a higher-order function to automate this transformation. We can write a curry function that takes any multi-argument function and returns its curried version.
This is a common task in functional programming libraries (like Lodash's _.curry). Building one yourself is an excellent way to solidify your understanding of closures, recursion, and modern JavaScript features.
Here is an advanced implementation.
function curry(func) {
// Return a new function that will collect arguments.
return function curried(...args) {
// 1. If we have enough arguments, call the original function.
if (args.length >= func.length) {
return func.apply(this, args);
} else {
// 2. Otherwise, return a new function that waits for the *next* arguments.
return function(...args2) {
// When called, recursively call `curried` with all arguments collected so far.
return curried.apply(this, args.concat(args2));
}
}
};
}
// --- Example Usage ---
function sum(a, b, c) {
return a + b + c;
}
const curriedSum = curry(sum);
console.log(curriedSum(1, 2, 3)); // 6 (works like the original)
console.log(curriedSum(1)(2, 3)); // 6 (partially applying)
console.log(curriedSum(1)(2)(3)); // 6 (fully curried)
This implementation is powerful because it allows a function to be called in multiple ways. The article below, which you may have seen referenced, explains this exact implementation.
This article provides a concise and clear explanation of currying and the implementation of a generic curry utility.
Read from the beginning to the end of the Advanced curry implementation section. The explanation of the two if branches in the curried wrapper is the most important part to focus on. Also, read the final Summary to reinforce the main points.
Conclusion
In this lesson, you've learned how to transform general, multi-argument functions into specialized, composable units. This is a fundamental skill in functional JavaScript that leads to more abstract and reusable code.
Key Takeaways:
- Partial Application is the process of creating a new function by pre-filling some arguments of an existing one. It's often a manual process to create a specific helper function.
- Currying is the structural transformation of a function with N arguments into a chain of N functions, each taking a single argument.
- Currying makes partial application trivial: calling a curried function with fewer than the total number of arguments naturally returns a partially applied function.
- Both techniques rely on closures to "remember" the arguments that have already been supplied.
- The primary goal is to create specialized functions from general ones and to make multi-argument functions compatible with compositional patterns like
pipeandcompose.
In our next lesson, we'll take a closer look at the rest and spread operators. You've already seen them used (...args) in our curry function, and we'll now explore their full capabilities with function arguments and array literals.