# How functions pattern match in Elixir

This blog post was originally published on Elixir School as part of the lesson on Pattern Matching. This lesson is, of course, a collaboration with many other open source contributors over at Elixir School. Please check out the source of the lesson for the full list of contributors, and feel free to put in a pull request to help us keep improving Elixir School for others! And without further interruption, on to the lesson…

Behind the scenes, functions are pattern-matching the arguments that they’re called with.

Say we needed a function to accept a map but we’re only interested in using a particular key. We can pattern-match the argument on the presence of that key like this:

`defmodule Greeter1 do def hello(%{name: person_name}) do  IO.puts “Hello, “ <> person_name endend`

Now let’s say we have a map describing a person named Fred:

`iex> fred = %{…> name: “Fred”,…> age: “95”,…> favorite_color: “Purple” …> }`

These are the results we’ll get when we call `Greeter1.hello/1` with the `fred `map:

`# call with entire map…> Greeter1.hello(fred)“Hello, Fred”`

What happens when we call the function with a map that doesn’t contain the `:name` key?

`# call without the key we need returns an error…> Greeter1.hello(%{age: “95”, favorite_color: “Purple”})** (FunctionClauseError) no function clause matching in Greeter3.hello/1 `
`   The following arguments were given to `Greeter3.hello/1`:    # 1    %{age: “95”}`
`    iex:12: Greeter3.hello/1`

The reason for this behavior is that Elixir pattern-matches the arguments that a function is called with against the arity the function is defined with.

Let’s think about how the data looks when it arrives to `Greeter1.hello/1`:

`# incoming mapiex> fred = %{…> name: “Fred”,…> age: “95”,…> favorite_color: “Purple” …> }`

`Greeter1.hello/1` expects an argument like this:

`%{name: person_name}`

In `Greeter1.hello/1`, the map we pass (`fred`) is evaluated against our argument (`%{name: person_name}`):

`%{name: person_name} = %{name: “Fred”, age: “95”, favorite_color: “Purple”}`

It finds that there is a key that corresponds to `name` in the incoming map. We have a match! And as a result of this successful match, the value of the `:name` key in the map on the right (i.e. the `fred` map) is bound to the variable on the left (`person_name`).

Now, what if we still wanted to assign Fred’s name to `person_name` but we ALSO want to retain awareness of the entire person map? Let’s say we want to `IO.inspect(fred)` after we greet him. At this point, because we only pattern-matched the `:name` key of our map, thus only binding the value of that key to a variable, the function doesn’t have knowledge of the rest of Fred.

In order to retain it, we need to assign that entire map to its own variable for us to be able to use it.

Let’s start a new function:

`defmodule Greeter2 do def hello(%{name: person_name} = person) do  IO.puts “Hello, “ <> person_name  IO.inspect person endend`

Remember that Elixir will pattern match the argument as it comes in. Therefore in this case, each side will pattern match against the incoming argument and bind to whatever it matches with. Let’s take the right side first:

`person = %{name: “Fred”, age: “95”, favorite_color: “Purple”}`

Now, `person` has been evaluated and bound to the entire fred-map. We move on to the next pattern-match:

`%{name: person_name} = %{name: “Fred”, age: “95”, favorite_color: “Purple”}`

Now this is the same as our original `Greeter1` function where we pattern matched the map and only retained Fred’s name. What we’ve achieved is two variables we can use instead of one:

1. `person`, referring to `%{name: “Fred”, age: “95”, favorite_color: “Purple”}`
2. `person_name`, referring to `“Fred”`

So now when we call `Greeter2.hello/1`, we can use all of Fred’s information:

`# call with entire person…> Greeter2.hello(fred)“Hello, Fred”%{age: “95”, favorite_color: “Purple”, name: “Fred”}`
`# call with only the name key…> Greeter4.hello(%{name: “Fred”})“Hello, Fred”%{name: “Fred”}`
`# call without the name key…> Greeter4.hello(%{age: “95”, favorite_color: “Purple”})** (FunctionClauseError) no function clause matching in Greeter2.hello/1 `
`  The following arguments were given to Greeter2.hello/1:    # 1    %{age: “95”, favorite_color: “Purple”}`
` iex:15: Greeter2.hello/1`

So we’ve seen that Elixir pattern-matches at multiple depths because each argument matches against the incoming data independently, leaving us with the variables to call them by inside our function.

If we switch the order of `%{name: person_name}` and `person` in the list, we will get the same result because each are matching to fred on their own.

We swap the variable and the map:

`defmodule Greeter3 do def hello(person = %{name: person_name}) do  IO.puts “Hello, “ <> person_name  IO.inspect person endend`

And call it with the same data we used in `Greeter2.hello/1`:

`# call with same old Fred…> Greeter3.hello(fred)“Hello, Fred”%{age: “95”, favorite_color: “Purple”, name: “Fred”}`

Remember that even though it looks like `%{name: person_name} = person}` is pattern-matching the `%{name: person_name}` against the `person` variable, they’re actually each pattern-matching to the passed-in argument.

Summary: Functions pattern-match the data passed in to each of its arguments independently. We can use this to bind values to separate variables within the function.

Thanks for reading! Want to work on a mission-driven team that loves Elixir and contributing to open source projects? We’re hiring!