code.cycling
code.cycling

Reputation: 1274

How to pattern match in Elixir?

I'm new to elixir and I was trying to pattern match but can't seem to get it right.

I have a decoded variable that has a value of

{:ok,
 %{
   "_id" => "5b162c483d1f3152b7771a18",
   "exp" => 1529286068,
   "iat" => 1528422068,
   "password" => "$2a$10$hlTl8vV0ENjpRxI1tRVAi.Woxx.na36K/lbZm7FrqLoXfzyoVzFia"
 }}

or

{:error, :invalid_token}

and I tried to use if else statement here but its always going to the if statement

if { decoded, :ok } do
    IO.inspect(decoded)
  else
    IO.puts('The token is invalid');
end

Upvotes: 0

Views: 247

Answers (2)

pyae phyo hlaing
pyae phyo hlaing

Reputation: 383

In elixir, a = 1 does not mean we are assigning 1 to the variable like other programming languages.

The equal sign means we are asserting that the left hand side is equal to the right hand side. It is like basic algebra.

For example,
iex> a =1
1
iex> 1=a (You can't do that in non-functional language)
1

In your example, you have to match tuples by using pattern matching.

And for your case, you can do with pattern matching and case statement like below.

fine = {:ok,
%{
   "_id" => "5b162c483d1f3152b7771a18",
   "exp" => 1529286068,
   "iat" => 1528422068,
   "password" => "pass"
}}

notfine = {:error, :invalid_token}

input = fine # It can be fine or not fine 

case input do
    #Here do pattern matching with incoming tuple
    {:ok,decoded} -> IO.inspect(decoded)
    {:error,decoded} -> IO.puts("The token is invalid")
end

Upvotes: 4

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121010

Pattern matching has nothing to do with conditional operators, even more, it’s used mostly to avoid using conditional operators which are considered by some of us to be evil.

Pattern matching operator is =. When you do foo = 42, you actually pattern match 42 to [yet unbound] foo variable. That is why the below is perfectly valid:

foo = 42
42 = foo # will succeed!
#⇒ 42 
:bar = foo # will raise
# ** (MatchError) no match of right hand side value: 42

Turning back to your example:

ok =
  {:ok,
   %{
     "_id" => "5b162c483d1f3152b7771a18",
     "exp" => 1529286068,
     "iat" => 1528422068,
     "password" => "pass"
  }}

ko = {:error, :invalid_token}

value = ok

case value do
  {:ok, decoded} ->
    IO.inspect decoded, label: "Decoded"
  {:error, :invalid_token} ->
    IO.puts "Invalid token"
  {:error, unknown} ->
    IO.inspect unknown, label: "Unknown error"
end 

Elixir will go through all the case clauses, trying to pattern match the argument to all the clauses one by one. The very first succeeded will be executed, and the yet unbound variables will be bound (decoded in the example above.)


Sidenote: Elixir has a great guide and great docs, and one might consider reading it instead of wasting time on unsuccessful attempts and SO questions. Here is a part on pattern matching.

Upvotes: 3

Related Questions