January 2nd, 2019 · Written by Nick Vernij
Pattern matching in Elixir is awesome, this post shows some examples where you can use it.
I have started using Elixir a little less than a year ago, looking back at this year I have learned a lot about functional programming and Elixir in particular. We currently use Elixir in production, as a graphQL back-end, and it works like a charm.
The feature I love most is pattern matching, there are so many possibilities where I find ways to reduce the use of nested if-else blocks.
To quickly explain pattern matching, here is a little example:
# called with 1 apple
def say_apples(1), do: IO.puts("You have 1 apple")
# called with any other amount that 1
def say_apples(amount), do: IO.puts("You have " <> amount <> "apples")
By defining a literal as a function argument, we are matching against
that literal. Meaning that when I call say_apples
with a
first argument of 1
, it will execute the method has a
matching 1
in its method definition.
Using an identifier, as you normally would when writing methods, will match with anything. Be aware that matching happens in the order you function are written in. When your first method definition matches with everything, any methods below will never be called.
So let's get to the point, here are 7 examples!
# true when the number is lower than 10
def lower_than_ten(number) when number < 10, do: true
# false when the number is higher than 10
def lower_than_ten(number), do: false
The when
keyword can be used to execute expressions when
matching, for example comparing the given argument.
# prints the name of the type
def print_type_name(%User{}), do: IO.puts("user")
def print_type_name(%Post{}), do: IO.puts("post")
While I won't go into the details of Elixir's type system, you'll want to match whether a struct is a certain type at some point.
# says hi to our user
def say_hi(%User{name: name}) do
IO.puts("Hiya, " <> name)
end
Structs are basically a key-value store, and sometimes you need one
specific variable. I feel like in those cases, the above example reads
way better than doing user.name
in the method body.
# returns whether is_admin is true
def can_administer(%User{is_admin: true}), do: true
def can_administer(_), do: false
We can even pattern match on the value inside struct properties. Woah!
Also notice how we use a _
if we don't really wanna use a
variable but still want to match with everything.
I could just return
is_admin
, I know, but this is an example :)
# returns true if a string starts with "foo"
def starts_with_foo("foo" <> _), do: true
def starts_with_foo(_), do: false
We can even use the concatenation operator in a method signature, to see if a string is prefixed with a certain string.
# returns the first item in an array
def first([f | _]), do: f
first([1, 2, 3])
will return 1
# returns everything but the first item in an array
def tail([_ | t]), do: t
tail([1, 2, 3])
will return [2, 3]
The possibilities are endless! What are your favorite Elixir features?
« Go Back