jonnifyelixir

F2 · Functional Programming

Composition & pipelines

Functional programs are built by joining small functions into larger ones. Composition wires the output of one function into the input of the next; the pipe operator writes that wiring left to right. A pipeline is a run of stages, each transforming the value on its way through.

Two notations describe the same idea. f(g(x)) composes f after g — g runs first, even though it is written second. The pipe rewrites this as x |> g() |> f(), reading in the order things happen. Most Elixir is pipelines: take a value, thread it through map, filter, and reduce, and read it top to bottom.

x |> f |> g |> h

x = 3 |> f add one +1 |> g double ×2 |> h take four −4 result ·

3 |> f |> g |> h — the value 3 waits at the input.
nested: h(g(f(3))) — same computation, read inside-out.

Compose: f after g

Composing two functions feeds the result of the first into the second. With inc then double, the value gains one, then doubles. The order is fixed by the nesting: the inner function runs first.

Set the input and watch it pass through both.

composition
building a function by feeding one’s output into another.
pipe operator
|> — passes the value on its left as the first argument on its right.
pipeline
a sequence of stages a value flows through.
point-free
combining functions without naming the value they act on.

double(inc(x)) · inc runs first

3
3 inc (+1) 4 double (×2) 8 result 8


      
double(inc(3)) = double(4) = 8

F1.03 · composition

The algebra is the same; here it is two Elixir functions joined.

Elixir

A composed function is itself a function — fn x -> f.(g.(x)) end.

Composition feeds output into input. With double(inc(x)), the inner inc runs first.

The pipe

The pipe operator writes the same chain in execution order. x |> inc() |> double() reads “take x, add one, then double” — the value moves left to right, each stage receiving it as its first argument. It computes exactly what double(inc(x)) does.

Compare the nested form with the pipe.

x |> inc() |> double() · left to right

3
3 |> inc() |> double() = 8 same as nested double(inc(3)) = 8


      
3 |> inc() |> double() · reads left to right · 8

Idea

The pipe reorders the text to match the order of operations.

Elixir

x |> f(a) means f(x, a) — x is the first argument.

The pipe is composition you read forwards. x |> inc() |> double() equals double(inc(x)).

A pipeline of stages

Chain the higher-order functions from F2.05 and you have a pipeline. Double every number, keep the ones past a threshold, then sum them — each stage hands its list to the next. Adjust the range and the threshold to watch the stages respond.

Set the range and the filter threshold.

map → filter → sum · each stage transforms the value

6
6
1..n [1, 2, 3, 4, 5, 6] |> map(&1 * 2) [2, 4, 6, 8, 10, 12] |> filter(> k) [8, 10, 12] |> sum() 30


      
1..6 → doubled → kept 3 over 6 → sum 30

F2.05 · folds

map, filter, and reduce are the stages a data pipeline is built from.

F2.09 · the lab

The pipeline lab takes this further over a real dataset.

A pipeline is composition over collections: each stage transforms the value and passes it on.

Three deep dives

This module continues across three pages: composing functions by hand, the pipe operator in full, and building a pipeline stage by stage. Read them in order.

F2.08.1
Function composition
Composing by hand — f after g — why the order matters, and chaining three together.
F2.08.2
The pipe operator
Threading a value as the first argument, reading left to right, and passing extra arguments.
F2.08.3
Building pipelines
Composing map, filter, and reduce over a dataset, watching the value transform at each stage.

What this lands

Composition joins functions so one’s output becomes the next’s input; the pipe operator writes that chain in reading order, passing each value along as the first argument. String the higher-order functions together and a pipeline emerges, each stage transforming a collection on its way through. The three deep dives cover composing by hand, the pipe in full, and building a pipeline; F2.09 then puts it to work in the data-pipeline lab.

Start with function composition, then the pipe operator, then building pipelines. Next module: F2.09 — The data-pipeline lab.