The Amazing Pipe Operator: |>

I’ve saved the best for last, at least when it comes to functions.

We’ve all seen code like this:

 people = DB.find_customers
 orders = Orders.for_customers(people)
 tax = sales_tax(orders, 2018)
 filing = prepare_filing(tax)

Bread-and-butter programming. We did it because the alternative was to write

 filing = prepare_filing(sales_tax(Orders.for_customers(DB.find_customers), 2018))

and that’s the kind of code that you use to get kids to eat their vegetables. Not only is it hard to read, but you have to read it inside out if you want to see the order in which things get done.

Elixir has a better way of writing it:

 filing = DB.find_customers
  |> Orders.for_customers
  |> sales_tax(2018)
  |> prepare_filing

The |> operator takes the result of the expression to its left and inserts it as the first parameter of the function invocation to its right. So the list of customers the first call returns becomes the argument passed to the for_customers function. The resulting list of orders becomes the first argument to sales_tax, and the given parameter, 2018, becomes the second.

val |> f(a,b) is basically the same as calling f(val,a,b), and

 list
 |> sales_tax(2018)
 |> prepare_filing

is the same as prepare_filing(sales_tax(list, 2018)).

In the previous example, I wrote each term in the expression on a separate line, and that’s perfectly valid Elixir. But you can also chain terms on the same line:

 iex>​ (1..10) |> Enum.map(&(&1*&1)) |> Enum.filter(&(&1 < 40))
 [1, 4, 9, 16, 25, 36]

Note that I had to use parentheses in that code—the & shortcut and the pipe operator fight otherwise.

Let me repeat that—you should always use parentheses around function parameters in pipelines.

The key aspect of the pipe operator is that it lets you write code that pretty much follows your spec’s form. For the sales-tax example, you might have jotted this on some paper:

To take this from a napkin spec to running code, you just put |> between the items and implement each as a function.

 DB.find_customers
  |> Orders.for_customers
  |> sales_tax(2018)
  |> prepare_filing

Programming is transforming data, and the |> operator makes that transformation explicit.

And now this book’s subtitle makes sense.