ReviseAlgo Logo

Functions

Function Composition & Currying

Master advanced functional programming in JavaScript. Explore function currying, partial application, and function composition patterns.

Last Updated: July 15, 2026 12 min read

1. Introduction

In functional programming, complex tasks are solved by combining simple, single-responsibility functions. Two key patterns for doing this are Currying (converting a multi-argument function into a series of single-argument functions) and Function Composition (combining multiple functions to create a new one).

2. Why It Matters

These patterns let you write modular and reusable code. Currying helps you configure functions ahead of time (partial application), while composition lets you build complex data processing pipelines out of simple, testable functions.

3. Real-World Analogy

Think of a Custom Gift Wrapper:

  • Currying (Stationery Steps): Instead of requiring box size, paper color, and ribbon type all at once, you configure the station step-by-step: first select the box size (returns a station configured for that box), then wrap it in your chosen paper (returns a wrapped box station), and finally add the ribbon (produces the final wrapped gift).
  • Function Composition (Assembly Pipeline): A pipeline where package size is measured (Step 1), then wrapped (Step 2), and finally labeled (Step 3). The output of each step becomes the input for the next, producing a finished product from a series of independent actions.

4. Function Currying

Currying converts a function with multiple arguments, like f(a, b, c), into a chain of nested single-argument functions: f(a)(b)(c).

5. Function Composition

Function composition is the process of passing the output of one function as the input to another. Mathematically, composing functions f and g is written as f(g(x)).
In JavaScript, composition is often implemented using a helper function that chains calls from right to left (like lodash's flowRight or compose):

6. Practical Example

Here is an example demonstrating using a curried logger function to create custom log formats:

7. Common Mistakes

  • Confusing currying with partial application: Currying transforms a function into a chain of single-argument functions. Partial application binds some arguments to a function, returning a function that accepts the remaining arguments.
  • Incorrect composition order: Forgetting that standard functional composition evaluates functions from right to left (inside-out), which can lead to unexpected pipeline errors.

8. Quick Quiz

Q1: What is the direction of execution in a standard function composition pipeline?

A) Left to right

B) Right to left

Answer: B — Mathematical and functional composition (f(g(x))) runs right-to-left (inner function g runs first, then outer function f).

9. Scenario-Based Challenge

The API Response Formatter:

An API outputs user records. You need to build a processing pipeline that filters out inactive users, extracts their emails, and formats them in lowercase. Write a clean composition implementation using filter, map, and standard composition helpers.

10. Debugging Exercise

Identify and fix the binding bug in this curried calculation function:

// Objective: Curried function to compute volume (w * h * d)
const getVolume = w => h => d => {
  w * h * d; // logical omission!
};
console.log(getVolume(2)(3)(4)); // prints undefined!
View Solution

Diagnosis: The final nested arrow function uses curly braces { ... } but is missing the return keyword, returning undefined.

Fix: Either include the return keyword, or use implicit return syntax by removing the curly braces:

// Option 1: Implicit return syntax
const getVolume = w => h => d => w * h * d;

// Option 2: Explicit return const getVolume2 = w => h => d => { return w * h * d; };

11. Interview Questions

🟢 Q1: Write a generic currying helper function that converts any function into its curried version.

Answer: Here is a standard implementation:

function curry(fn) {
  return function curried(...args) {
    if (args.length >= fn.length) {
      return fn.apply(this, args);
    }
    return function(...args2) {
      return curried.apply(this, args.concat(args2));
    };
  };
}

12. Production Considerations

  • Readability: While currying and composition are powerful, overusing them can make code harder for other developers to read if they are not familiar with functional programming. Use them where they clarify data flow, but avoid over-engineering simple logic.