Pattern Matching, Revisited
Not too long ago I started learning Elixir. One of the things that make Elixir a pleasure to work with is pattern matching. So in this post I will explain a little bit about how pattern matching works.
The Match Operator
First things first, I will start with the match operator. The match operator looks like this
=. The match operator is what we commonly know as the equals sign
=. But it doesn't work the way you might think it works. Initially it was hard for me to wrap my head around the match operator, since in most other languages it is used for assigning values to variables. With Elixir the
= does a little more than assigning values. It is more comparable to the equals sign in algebra. It is used for asserting the expressions on the left side of the operator is equal to the expressions on the right side.
Let's try and do the same matching as above but with more complex data structures:
As mentioned earlier, you can ressign a value to a variable with the match operator if the variable is on the left side. You can also make it so that a variable cannot be reassigned, by using the the pin operator. A pin operator is this symbol
^. The pin operator forces a strict match against it's already existing value. So in the example below we have assigned 1 to x, so x cannot equal 2, since it already equals 1.
In the following example I used '|' known as a pipe or vertical bar. The element before the pipe is the head, and I am assigning it the variable 'head'. And all that comes after the pipe is the tail, and I am assigning it the variable 'tail'.
This syntax makes it easier to iterate through a collection, since in Elixir you must iterate recursively.
Using the pipe in a list also allows you to add elements to the list.
Here is a more realisic example of how you can take advantage of the destructuring along with pattern matching. You can pattern match parts of a data structure, and extract out the data you need. I am assigning the variable 'message' to the string "Success!". That way we can extract out the individual message.
Sometimes there are cases where you only care about specific values of the match. That's when you can use an underscore as a placeholder. The underscore acknowledges that there is some value there, and it will just match to whatever it is. This allows you to ignore the value the underscore contains.
If you want to make sure that there should be some value where the underscore is, you can give it a variable name by adding a name after the underscore. The problem with this however is that it will return a value along with a warning message. It might send a more clear message to have an underscore by itself if you don't want someone to be using that value behind the underscore.
Pattern Matching in functions
A more real worldly example would could be something like validations or error handling.
Elixir is immutable and it relies on recursion to make loops. So it will continue calling itself until a condition is met. Here with the combination of pattern matching and multiple function definitions I have achieved recursion very easily.
The function definition with the 0 comes first with each iteration it will check if 'n' is equal to 0. If it is not equal to 0 it will go to the next function definition where it will say "Hey" and decrement n, until it reaches 0, and finally say "Yo".
In summary I have talked about:
- The match operator - compares values on the left side of the sign to the right side
- The pin operator - allows the value that was previously assigned to remain as the same value
- Destructuring - allows extracting out values from other data structures or functions
- Underscore - allows some values to be ignored from the match
- The use of pattern matching as conditionals in functions
- The use of pattern matching as conditionals in recursion
I hope this helped in your understanding of how to use pattern matching.