20
votes

I am curious when I should be using pattern matching vs guard clauses when defining functions.

For example with pattern matching:

defmodule Exponent do
  def power(value, 0), do: 1
  def power(value, n), do: value*power(value, n-1)
end

vs guard clause:

defmodule Exponent do
  def power(value, n) when n==0, do: 1
  def power(value, n), do: value*power(value, n-1)
end

I mean both produce the same result but is one solution preferred over the other? And if so why?

I'm new to Elixir, so the answer to this question is not readily apparent to me (yet). Thanks in advance.

1
Do you observe any performance difference in one construct versus the other? Asking if one is preferred over the other strikes me as a great example of a question that wants an opinion if there's no performance difference. Vote to close. - Onorio Catenacci
I'm honestly so new I haven't yet discovered how to even benchmark this kind of thing... I also did not see similar questions so I decided to explicitly ask. - aren55555
There may be a difference between one implementation and the other but without any context it's hard to tell. Right now you're asking a question analogous to "which is better, bananas or strawberries?" - Onorio Catenacci
I guess rather than asking for a "preferred" solution I should have been asking which is preferred for performance reasons (as they both accomplish the same end result). - aren55555

1 Answers

23
votes

Guards are more powerful than pattern matching, but they introduce a layer of complexity that might be unnecessary. For simple equality checks like in your example, they should be equivalent in terms of performance. I recommend trying to use pattern matching first in order to keep things simple. You can then fall back to a guard clause if absolutely necessary. Yet, it might occasionally make sense to do otherwise when it aids readability, e.g.

def sign(x) when x  < 0, do: -1
def sign(x) when x == 0, do:  0
def sign(x) when x  > 0, do:  1

I suppose the "proper" use case for the equality operator in guard clauses is when it is used as part of more complex expressions, e.g.

def divisible?(x, divisor) when rem(x, divisor) == 0, do: true
def divisible?(_x, _divisor), do: false