Higher-Order Functions & Currying

Medium100% Free~20 mins#higher-order-functions#currying#composition#pipe#closures#functional-programming
Key Learning Objectives
✓

Understand higher-order functions: functions that accept or return other functions.

✓

Master currying and partial application using lexical closures.

✓

Distinguish between function composition (right-to-left) and pipeline execution (left-to-right).

✓

Apply pure functions without side effects to maintain deterministic application state.

The Interview Problem

What is logged to the console when the following code executes, and how does the execution order differ between pipe() and compose()?

1const add = (a) => (b) => a + b;
2const multiply = (a) => (b) => a * b;
3
4const addFive = add(5);
5const double = multiply(2);
6
7const pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);
8const compose = (...fns) => (x) => fns.reduceRight((v, f) => f(v), x);
9
10const pipeline = pipe(addFive, double);
11const composed = compose(addFive, double);
12
13const res1 = add(3)(4);
14const res2 = pipeline(10);
15const res3 = composed(10);
16
17console.log(res1, res2, res3);
Predict Console Output
Interactive Challenge

Select the option that matches what standard ECMAScript prints to the console:

7 30 25

7 25 25

7 30 30

12 25 30

V8 Engine Execution Trace
Step 1 of 9 (Line 1)

Global Execution Context allocates curried function generators add and multiply in heap memory.

Call Stack (Top = Active)
Global Execution Context
Lexical Scope / Bindings
add:FunctionRef#add
multiply:FunctionRef#multiply
Console Stream
> [empty]

Deep Technical Breakdown

Higher-Order Functions, Currying & Composition

  1. First-Class & Higher-Order Functions: In JavaScript, functions are first-class citizens: they can be assigned to variables, passed as arguments, and returned from other functions. A Higher-Order Function (HOF) is any function that takes one or more functions as arguments or returns a function.
  2. Currying vs Partial Application:
    • Currying: Transforming a function with arity $n$ into $n$ consecutive functions that each accept exactly one argument: f(a, b, c) -> f(a)(b)(c).
    • Partial Application: Fixing a subset of arguments to produce a function of lower arity: f(a, b, c) -> f(1)(b, c).
    • Both patterns rely on lexical closures to preserve outer argument bindings across invocations.
  3. Function Composition (compose vs pipe):
    • Pipe (pipe(f, g, h)(x)): Left-to-right execution. Implemented with Array.prototype.reduce: x |> f |> g |> h -> h(g(f(x))).
    • Compose (compose(f, g, h)(x)): Right-to-left execution. Implemented with Array.prototype.reduceRight: f(g(h(x))).
Common Traps & Mistakes

Reversing the execution order of `compose()` and `pipe()`. In interviews, `pipe` is left-to-right; `compose` is right-to-left.

Introducing side effects (like mutating an external array or global object) inside curried functions, destroying referential transparency.

Creating memory leaks by retaining large objects inside long-lived closures generated by currying.

FAANG Follow-Up Probes
Probe #1

How would you write a general auto-curry function in JavaScript that supports variable argument arity (e.g. curry(fn)(1, 2)(3) and curry(fn)(1)(2, 3))?

Probe #2

How does Redux apply compose() to middleware enhancers in applyMiddleware()?

Probe #3

What is Point-Free programming (tacit programming), and what are its trade-offs in frontend codebases?