0Pricing
JavaScript Academy · Lesson

Building pipe and compose

Implement left-to-right and right-to-left composition.

Building pipe and compose is a free JavaScript Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the JavaScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

From Two Functions to Many

A two-argument compose is limiting. Real pipelines chain many steps. In this lesson you will build general-purpose compose and pipe using reduce and reduceRight.

pipe: Left to Right

pipe reads in execution order: the first function runs first. pipe(a, b, c)(x) equals c(b(a(x))). Most people find this more natural than compose.

const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);

const inc = n => n + 1;
const double = n => n * 2;

console.log(pipe(inc, double)(5));

How reduce Drives pipe

reduce starts with the input value as the accumulator and applies each function in turn, feeding each result into the next. The initial value x seeds the chain.

const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);

const steps = pipe(
  n => n + 1,
  n => n * 3,
  n => n - 2
);

console.log(steps(4));

compose With reduceRight

compose is pipe reversed. Using reduceRight walks the function list from the end, so the rightmost function runs first, matching f(g(x)).

const compose = (...fns) => x => fns.reduceRight((acc, fn) => fn(acc), x);

const inc = n => n + 1;
const double = n => n * 2;

console.log(compose(inc, double)(5));

pipe and compose Are Mirrors

The same function list gives different results in pipe versus compose because the direction flips. Choose based on how you want to read the steps.

const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
const compose = (...fns) => x => fns.reduceRight((acc, fn) => fn(acc), x);

const inc = n => n + 1;
const square = n => n * n;

console.log(pipe(inc, square)(3));
console.log(compose(inc, square)(3));

compose as Reversed pipe

You can define compose in terms of pipe by reversing the function list. This shows how closely related they are.

const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
const compose = (...fns) => pipe(...fns.reverse());

const inc = n => n + 1;
const double = n => n * 2;

console.log(compose(inc, double)(5));

A Real Text Pipeline

Build a slug generator from tiny string functions using pipe. Each step does one job and is easy to test alone.

const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);

const slugify = pipe(
  s => s.trim(),
  s => s.toLowerCase(),
  s => s.replace(/\s+/g, '-')
);

console.log(slugify('  Hello World Example  '));

Composing Array Operations

Pipelines work on any data type, including arrays. Combine filtering and mapping into one named transform.

const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);

const process = pipe(
  arr => arr.filter(n => n % 2 === 0),
  arr => arr.map(n => n * 10)
);

console.log(process([1, 2, 3, 4, 5, 6]));

The Identity Edge Case

Calling pipe() with no functions returns the input unchanged, because reduce just returns the seed. This identity behavior makes the helpers safe to call with zero steps.

const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);

const identity = pipe();
console.log(identity(42));
console.log(identity('unchanged'));

Combining With Currying

Curried, partially applied functions plug straight into pipelines. Each becomes a clean one-argument step.

const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
const add = a => b => a + b;
const times = a => b => a * b;

const calc = pipe(add(3), times(2), add(-1));
console.log(calc(5));

Choosing pipe or compose

Use pipe when you want steps to read top-to-bottom in execution order. Use compose when matching mathematical f(g(x)) notation. Both are one-line reduce wrappers, and both are everywhere in functional libraries.

const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);

const normalize = pipe(
  s => s.trim(),
  s => s.replace(/[^a-z0-9]+/gi, ' '),
  s => s.toUpperCase()
);

console.log(normalize('  a-b_c!d  '));

Quick Check

Which array method makes compose run functions right-to-left?

Recap: pipe and compose

You built general composition helpers:

  • pipe uses reduce for left-to-right execution.
  • compose uses reduceRight for right-to-left execution.
  • compose can be defined as pipe with a reversed list.
  • Empty pipelines act as identity, and curried steps slot in cleanly.

Frequently asked questions

Is the “Building pipe and compose” lesson free?

Yes — the full text of “Building pipe and compose” is free to read here on the web, and the JavaScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the JavaScript Academy course, upgrade to CoddyKit PRO.

What will I learn in “Building pipe and compose”?

Implement left-to-right and right-to-left composition. You practise JavaScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start JavaScript Academy?

No prior experience is required. JavaScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Building pipe and compose” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this JavaScript Academy lesson?

Yes. Every JavaScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Partial Application
  2. Currying Functions
  3. Function Composition
  4. Building pipe and compose
← Back to JavaScript Academy