Elixir Tips #1: Function Clause Ordering

When defining a function with multiple clauses, try to structure the clauses such that the edge-cases are handled first.

Good

def pay_bill(%Bill{is_paid: true}), do: :ok

def pay_bill(%Bill{} = bill), do
  # Lots of logic
end

Bad

def pay_bill(%Bill{is_paid: false}) do
  # Lots of logic
end

def pay_bill(_bill), do: :ok

Defining the main clause second lets us simplify it by putting the conditions in the edge-case clause. The main clause can assume the state is good for it to do its work.

Also, the intention of the edge-case clause is clear. We see that we return :ok if the bill is paid. In the "Bad" example, we returned :ok from a mysterious catch-all clause.

This setup is reminiscent of guard clauses — where preconditions must be met before continuing execution.


Discuss on Twitter 💬