A little over a month ago I was introduced to an awesome functional language called Elixir. It’s a relatively young ecosystem but has plenty of useful libraries and frameworks like the Phoenix Web Framework which we use on my team here at IBM.

If you’ve ever used Ruby on Rails you will love Phoenix.

When I was learning Elixir there were a handful of foreign concepts I hadn’t seen in previous languages I’d worked with. The pipe operator is one of those concepts. It’s very useful once you get the hang of it.

Pipe Operator

The pipe operator looks like a right pointing triangle: |>

It is used to feed the output of a function as an argument to your next function.

Piping prevents nested function calls and looks like this:

"hello world"
|> foo()
|> bar()

Here, the function foo() will receive "hello world" as its first argument. We also chained our pipes to give bar() whatever foo() outputted previously.

If you feel confused, refer to this great explanation from stackoverflow.

With that said, let’s get into an example to make some sense of this 🤯.


Take this example of manipulating a list in JavaScript,

filterSort function in JavaScript

Now let’s rewrite the same thing in Elixir (3 different ways),

Elixir filterSort option 1 (bad)

The above example is the most similar to what we did in JavaScript. However, it’s really not a great way to do things in Elixir because much better tools are available to you.

Elixir filterSort option 2 (nested function calls)

Now this is looking a bit better, a one liner! This might not be so bad but add another layer of nesting or a second argument and you’ll quickly want to refactor.

Elixir filterSort option 3 (with pipes)

Now this is perfect, we have a function which takes advantage of pipes. It’s much easier to read than option 1 and easier to maintain than option 2.

Extra Tip

Debugging tip!

Add IO.inspect() to your pipe chain. In Elixir you use this to log/print to stdout. I.e. IO.inspect("Hello world") would output “Hello world”.

Using pipes we could do something like this to achieve the same result:

"Hello world"
|> IO.inspect()

This means we can add IO.inspect() to our above examples to see the state of our program after each function call.

Elixir filterSort with debugging

Now, we can easily see the state of our list after each manipulation and since IO.inspect returns its original argument, we don’t have to change much.


Thanks for checking out my first article on Elixir — one of my new favorite technologies. I hope you learned something new and I can’t wait to bring more guides soon!