Guards and pattern matching
We’ve looked at pattern matching with elixir earlier. We can use pattern matching with our functions as well. For instance, let’s say we want to write a function that checks to see if a number is zero or not.
We always will return true when the number passed in through a function is 0, so we can write our function like so:
defmodule Math do def zero?(0) do true end end
Alternatively, more succinctly, we can write this function in the list format to make it smaller:
defmodule Math do def zero?(0), do: true end
If we run this function in our REPL, we’ll see that we can call the
Math.zero?(0) without errors. However, if we run this with any other number, it will explode with an error.
It explodes with an error because elixir cannot find a function to run that matches the case where the argument is non-zero. We can write this function by defining a function version with an argument:
defmodule Math do def zero?(0), do: true def zero?(_) do false end # or, the one line version # def zero?(_), do: false end
Now if we run the function in our terminal with either 0 or a non-zero number, we can see it does not explode, but instead returns a boolean value of false.
What happens if our requirements change and we want to also say that the string “zero” is equal to zero? We might have to change our function to be more complex, right?
Not necessarily, we can use the concept of guards to add additional functionality to the pattern matching provided by default through Elixir. A guard comes right after the function definition. For instance, to implement our previous function with a guard to match if the argument is a string of “zero”, we can add the guard like so:
defmodule Math do def zero?(0), do: true def zero?(x) when x == "zero" do true end def zero?(_), do: false # or, the one line version # def zero?(x) when x == "zero", do: true end
Running this in the console and we’ll see that we get
true when we pass in the string of
Go on to Recursion.
Go back to Modules.