Check out the Alchemist's Edition

#24: Pattern Matching in Elixir

Elixir 1.4.5


One of features that makes Elixir such a great language is pattern matching.

In fact, in Elixir, the equals sign is called the match operator.

Let’s see why.

Let’s fire up iex and start with a simple example and set the string “a” to the variable a.

> a = "a"
"a"

And then let’s put the string “a” on the left side and our variable a on the right side.

> "a" = a
"a"

And because these match, meaning the left side equals the right side, the string “a” was returned.

Now let’s see what happens if the two sides are not equal.

> "b" = a
** (MatchError) no match of right hand side value: "a"

Elixir tells us there’s a MatchError - because both sides of the equals sign don’t match.

While this is a simple example, it does illustrate a good idea to keep in mind when doing pattern matching in Elixir - both sides of the equal sign need to match.

Now explore a few different ways we can use it.

One way we can use it is to pull values from different data structures by matching on them.

Let’s first try it with a map.

We’ll create create a map with some info about a person:

> person = %{name: "bill", age: 25}
%{age: 25, name: "bill"}

Now if we wanted to grab the name and age from our person map how could we do that with pattern matching?

Let’s try this - we’ll create a map on the left side, with name and age as variables for their respective keys. And if both sides of the equal sign match, our variables will be updated with the corresponding values.

> %{name: name, age: age} = person
%{age: 25, name: "bill"}

And it looks like it worked.

The variable age has been updated with the age of our person:

> age
25

And the variable name has been updated with the name:

> name
"bill"

Now let’s test out pattern matching with a list.

We’ll create a list of colors and we use pattern matching to deconstruct the whole list:

> colors = ["red", "blue", "green"]
> [red, blue, green] = colors
["red", "blue", "green"]

And now we see all of our variables have been updated to their corresponding element in the list.

> red
"red"
> blue
"blue"
> green
"green"

You’ll also see pattern matching play a role in another common pattern used in Elixir to break apart lists - specifically to separate the first element, or head, of the list from the remainder, or tail.

Let’s try it with our same list.

> [ head | tail ] = colors
["red", "blue", "green"]

And the head variable is now the string “red”.

> head
"red"

While the tail is a list made up of our original list minus the first element.

> tail
["blue", "green"]

As you write more Elixir, you’ll see pattern matching everywhere. And another common example is using an OK/Error tuple.

Let’s see what one looks like.

We’ll create our “OK” tuple where the first element is the atom :ok, and for the second element, we’ll create a message.

> data = {:ok, "Success"}
{:ok, "Success"}

And the we can grab our message by creating another tuple on the left side, that has the same atom :ok and then a variable that we can use to assign the second element in the tuple - the message.

> {:ok, msg} = data
{:ok, "success"}
> msg
"success"

And since both sides matched, the msg variable is now the string “Success”.

Now let’s take this example and build on it.

Imagine we have some movie API that responds with this structure when we try to create a movie with it.

Let’s create a function that will parse the response - grabbing either the success or error message - and return it.

Let’s create a file matcher.exs

Then we’ll create our new module Matcher

And inside we’ll define a function, get_msg, which will take our APIs response.

Then inside the function we’ll use a case statement to pattern match on the contents of the response.

If the first element in the response tuple is the atom :ok our first statement will execute.

And if the first element in the response tuple is the atom :error our second statement will execute.

matcher.exs

defmodule Matcher do

  def get_msg(response) do
    case response do
      {:ok, msg} ->
        "Success: #{msg}"
      {:error, msg} ->
        "Error: #{msg}"
    end
  end
end

Now let’s go to the command line and since this is a .exs file we can load it in iex with:

$ iex matcher.exs

Let’s create our success response. Then let’s pass that into our get_msg function

> success_response = {:ok, "Movie was created"}
{:ok, "Movie was created"}
> Matcher.get_msg(success_response)
"Success: Movie was created" 

And it returns our success message.

Now for our error response:

> error_response = {:error, "Problem creating the movie"}
{:error, "Problem creating movie"}
> Matcher.get_msg(error_response)
> "Error: Problem creating movie"

And our error message was returned.