Rethinking conditional logic in Elixir

Published September 30, 2018 by Toran Billups

In part 7 of my Elixir journey I wanted to share an example that has helped me rethink conditionals while working in the language.

Branching and Conditionals

The first time I wrote a function with conditional logic in Elixir it looked a lot like any other language I'd used in the past. I took inspiration from my procedural background using `if` and `else` to branch so I could sum all the numbers in a list.

    defmodule Math do
      def sum(list) do
        if (list === []) do
          0
        else
          [head | tail] = list
          head + sum(tail)
        end
      end
    end
  

This function worked well enough but it turns out most Elixir engineers aren't using `if` or `else` for conditional logic but instead pattern matching.

    defmodule Math do
      def sum([]), do: 0
      def sum([head | tail]) do
        head + sum(tail)
      end
    end
  

At first glance our named function `sum` has what appears to be multiple definitions. After some reading on the subject I've learned this is instead multiple clauses of the same function definition.

    Math.sum([1, 2, 3])
  

As we invoke the `sum` function Elixir tries to match the list of `[1, 2, 3]` against the first function's parameter `[]`. When the match fails it tries the second function's definition. This match is a success because Elixir can bind the list `[1, 2, 3]` to the second function's parameter `[head | tail]`

It took some time to completely wrap my head around pattern matching as the primitive for conditional logic but as I became more familiar with the concepts I started to enjoy writing code in a more functional style.


Buy Me a Coffee

Twitter / Github / Email