简体   繁体   中英

What is the purpose of match operator (=) in elixir?

I am reading Elixir's pattern matching and I am a little confused on = operator being a match operator.

The website says

Elixir, the = operator is actually called the match operator.

And it gives this example:

iex> x = 1
1
iex> x
1
iex> 1 = x
1
iex> 2 = x
** (MatchError) no match of right hand side value: 1

For some reason, I still don't understand what 1 = x is doing. It returns 1 if I put the value of the variable I had just assigned to the left of = and throws error if the value is not the same. I can't really see how this is useful.

What does it mean for = to be a match operator ? Is it similar to 1 == x (if so, why doesn't it return true/false )? When will I ever use match operator?

  1. What does it mean for = to be a match operator?

It means whether left can match the right, if their value are equal, they can match.

= can also use as bind, which may confused you. Note that bind is not equal to assign.

a = 1 is binding value 1 to a. 1 = a is check whether 1 matches a.

Variables as left operator are all binding, in this situation, bind can be confused with match in a =1 , so there is a syntax ^ call pin operator.

^a = 1 is check whether a matches 1.


  1. Is it similar to 1 == x (if so, why doesn't it return true/false)?

As mentioned in 1, it is not == . == is == in Elixir and will return true or false.

  1. When will I ever use match operator?

You will use it in function param match, map kv match, function return value match etc.

case song_id_info do
  "" -> ""
  {:ok, song_id} -> song_id
  {:error, reason} -> IO.puts "error get_song_id #{reason}"
end

This one is to match song_id_info with "" , {:ok, song_id} and {:error, reason} . When song_id_info not match one of them, error will be raised.


If you study deeper, you can know how match works perfectly at the end.

1 = x is the contrived example that probably fooled you. In general, match operator assures that the RHO matches LHO, meaning LHO has nothing violating what RHO has. It's not about the exact match since LHO might in general a) assure that only the part of RHO is matched and b) might be more permissive than the equality check ( == ).

In the case of 1 , well 1 is 1 , that's why the example looks contrived. On the other hand, = for the match operator is the common syntax, covering all the cases. 1 === 1 in javascript also looks a bit weird, and one might ask “why would I ever need triple-equal,” seeing this example only.

On the other hand, match operator uses in:

function clause matching

def print(1), do: ...
def print(other), do: ...

when print(my_var) is called somewhere in the code, the match operator is implicitly called on each clause, from top to bottom in the order of clauses declaration, to find the matched clause . That said, the following code:

defmodule M do
  def print(1), do: "Neo"
  def print(other), do: "toN Neo: #{other}"
end

my_var = 5
M.print(my_var)
#⇒ "toN Neo: 5"

is roughly equivalent to:

#    ⇓ HERE match operator is used
if 1 = my_var do # this alone would raise MatchError
                 # but bear with me: ErlangVM
                 # takes care of that when finding
                 # a proper clause and it indeed
                 # uses match operator, not `==`
  "Neo"
else
  "toN Neo: #{other}"
end

case matching

case my_var do
  1 -> "Neo"
  other -> "noT Neo: #{other}"
end

the above is roughly the same as before.

plain code to selectively assign variables

The example below involves more complicated term than just an integer since my_new_var = my_var would be called binding , although this is just a terminology muddle and we could safely call it “matching” as well without loss of the generality.

%{foo: my_var} = %{foo: 42}

here my_var gets matched to 42 because LHO matches RHO in general and the key is the same.

The equality operator differs in two ways:

  • LHO must be exactly equal to RHO ( %{} == %{foo: 42} fails, while %{} = %{foo: 42} succeeds);
  • LHO is not matched assigning not yet bound variables ( %{foo: my_var} == %{foo: 42} fails with “undefined function my_var/0”).

The example of how match differs from equality operator in ruby (in ruby the role of match operator roughly plays triple-equal aka case-equal aka threequals):

/n/ === "One"                       #⇒ true
String === "One"                    #⇒ true
->(s) { s.length == 3 } === "One"   #⇒ true

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM