Explainstuff.mebeta
All concepts
Functional Programmingbeginner6 min

Pipelines

Stop reading code inside-out — let your data flow down an assembly line, one tidy step at a time.

Picture a factory assembly line. A raw part rolls in one end, passes a worker who drills a hole, slides to the next who paints it, then to the next who boxes it — and a finished product rolls out the far end. Nobody has to hold the whole machine in their head; each station does one small job and hands the result along. A pipeline in code is exactly this: your data flows through a series of small steps and comes out transformed at the end.

The problem

Without pipelines, chaining a few operations means nesting function calls inside each other. Say you want to take some numbers, keep the even ones, square them, and add them up. Written as nested calls it looks like this:

List.sum (List.map (fun x -> x * x) (List.filter (fun x -> x % 2 = 0) [1..10]))

The trouble is that this reads inside-out. The first thing that happens (List.filter) is buried deep in the middle, and the last thing (List.sum) is way out on the left. Your eyes have to dig to the center, then unwind outward — the exact opposite of the order things actually happen.

Watch out

The general shape h(g(f(x))) is sneaky: it grows a new layer of parentheses with every step. Add one more operation and you're hunting for which closing ) belongs to which call. The logic isn't hard — the reading is.

How it works

F# gives us the pipe operator |> to fix this. The rule is delightfully simple: |> takes the value on its left and feeds it in as the last argument to the function on its right. So x |> f is just another way of writing f x. On its own that's barely interesting — but chain a few together and the whole thing reads like a sentence, top to bottom.

[1..10]
|> List.filter (fun x -> x % 2 = 0)
|> List.map (fun x -> x * x)
|> List.sum

Read it straight down: "take 1..10, keep the evens, square them, then sum them." The order you read is the order it runs.

Data flows through the steps
|>
[1..10]
filter
map
sum
result
The |> operator pumps the value left-to-right through each function — read it like a sentence.

The animation above shows the heart of it: a value enters on the left, flows through each transform step in turn, and a final result pops out the right. Every step takes whatever the previous one produced and hands its own result to the next — no detours, no nesting, just a clean left-to-right flow you can follow with your finger.

Why it's so handy

Pipelines are exactly where transform, keep, and combine come to life — map, filter, and sum line up beautifully when you pipe between them. And the whole trick only works because F# lets you pass functions around as values: each step is a function waiting for the data to arrive.

Three nice things fall out of writing code this way:

  • Readable — the steps appear in the order they happen, so the code reads like a description of what it does.
  • Small and testable — each step does one little job, so you can check it on its own without untangling a giant expression.
  • Easy to change — want to drop the squaring or add a new filter? Insert or delete one line; the rest of the chain doesn't care.
Tip

When a pipeline gets long, format it like the example above: one |> per line. Now each step lines up vertically, and editing a step — or commenting one out to debug — is a one-line change instead of microsurgery on a wall of parentheses.

Key takeaways

  • Deeply nested calls like `h(g(f(x)))` read inside-out, which forces your eyes to jump around to follow the data.
  • A pipeline flips that around so data flows top-to-bottom and left-to-right through a chain of small steps.
  • In F#, the pipe operator `|>` takes the value on the left and feeds it as the last argument to the function on the right.
  • Pipelines are where transform, keep, and combine shine — and they only work because functions can be passed around as values.
  • Each step is small, testable, and easy to add, remove, or reorder without untangling the whole expression.

Keep going