The Pipe Operator

x |> f(y) is f(x, y) — the left value becomes the first argument.

x |> f(y) is f(x, y) — the left value becomes the first argument.

"  Hello World  "
|> String.trim()
|> String.downcase()
|> String.split()
|> Enum.map(&String.capitalize/1)
|> Enum.join(" ")
# "Hello World"

18.1 Pipeline idioms

# then/2 — pipe into a non-first position
5 |> then(&Enum.take([1, 2, 3, 4, 5, 6], &1))

# tap/2 — side effect, return the original value
data |> tap(&IO.inspect(&1, label: "debug")) |> process()

# IO.inspect returns its argument — great for debugging pipelines
list |> IO.inspect(label: "before") |> Enum.sort() |> IO.inspect(label: "after")

# dbg/1 (1.14+) prints every step of a pipeline
[1, 2, 3] |> Enum.map(&(&1 * 2)) |> Enum.sum() |> dbg()

18.2 Design functions for piping

Put the main data structure as the first argument (Map.put(map, k, v), String.replace(str, a, b)).

18.3 Anti-patterns

Don't pipe into anonymous functions directly: x |> (fn y -> y end).() — use then/2.

Avoid single-step pipes: foo |> bar() → bar(foo) (Credo flags this).