Elixir Pattern Matching in a nut shell
If you are new to Elixir, Pattern Matching may be something strange to you. When you get familiar with it, you will know how powerful it is. And …
In previous post, I explain what is Pattern Matching and how to use it.
Elixir pattern matching in a nutshell
Pattern matching is so cool but some time I want to do some more complicated checking. With pattern matching I can easily do this
1def can_access?(%User{paid_user: true}), do: true
Yes, Pattern matching can do check value with exact value easily. But for example, I want to allow user with level > 25
to access.
How to do that check with Pattern matching?
Pattern matching as it’s named, it is used to match data against pattern. If you want to do more complex check, you need another guy. That is where guard
shines, it is complement for Pattern Matching
1def can_access?(%User{level: level}) when level > 25, do: true
guard
Guard is a complement to your pattern matching to do more complex check.
Guard expression is invoke after pattern mattching
In many cases, Guard
and Pattern matching
can produce the same result, so use which you like.
1# sum on empty list
2# pattern matching
3def sum_list([] = _input), do: 0
4
5# guard
6def sum_list(input) when input == [], do: 0
Some example
Check primitive type
1def sum(a, b) when is_integer(a) and is_integer(b) do
2 a + b
3end
Check value is nil/ not nil
1def string_length(string) when not is_nil(string) do
2 # your code
3end
Check if input in a list of allowed values
1def can_edit?(%User{role: role}) when role in ["admin", "moderator"] do
2 true
3end
And many more …
Where you can use Pattern Matching, you can use Guard
case
block
1case value do
2 x when is_binary(x) -> String.to_integer(x)
3 x when is_integer(x) -> x
4 _ -> raise "Invalid value"
5end
with
block
1with user when not is_nil(user) <- find_user(id) do
2 # your code block
3end
function
clause as our example above
Not all expression will work with guard. Only a list of built-in guard
and combination of them work in guard expression.
Check this from https://hexdocs.pm/elixir/guards.html#list-of-allowed-expressions
- comparison operators (
==
,!=
,===
,!==
,>
,>=
,<
,<=
)- strictly boolean operators (
and
,or
,not
). Note&&
,||
, and!
sibling operators are not allowed as they’re not strictly boolean - meaning they don’t require arguments to be booleans- arithmetic unary and binary operators (
+
,-
,+
,-
,*
,/
)in
andnot in
operators (as long as the right-hand side is a list or a range)- “type-check” functions (
is_list/1
,is_number/1
, etc.)- functions that work on built-in datatypes (
abs/1
,map_size/1
, etc.)
Yes you can define a guard with defguard/1
and defguardp/1
. But you should only define your own guard if you have a really really reasonable reason to do so.
In my experience, I have never defined a guard my own, built-in guards are too enough.
With Pattern matching and Guard, you have a super powerful combo in your hand. Let’s code!
If you are new to Elixir, Pattern Matching may be something strange to you. When you get familiar with it, you will know how powerful it is. And …
The story At our company, OnPoint, we are building an ecommerce website using Phoenix Framework. And I am working on admin to manage product, orders …