With variables:
iex(2)> x = %{a: 1, b: 2}
%{a: 1, b: 2}
iex(3)> %{a: 1, b: 2} = y
** (CompileError) iex:3: undefined function y/0
With function parameter variables:
defmodule A do
def go1(z = %{a: a}) do
IO.inspect z
IO.puts a
end
def go2(%{a: a} = z) do
IO.inspect z
IO.puts a
end
end
In iex:
iex(4)> c "a.ex"
warning: redefining module A (current version defined in memory)
a.ex:1
[A]
iex(5)> map = %{a: 1, b: 2}
%{a: 1, b: 2}
iex(6)> A.go1(map)
%{a: 1, b: 2}
1
:ok
iex(7)> A.go2(map)
%{a: 1, b: 2}
1
:ok
Function args are pattern matched to the function parameter variables. And, in elixir function parameters can be constants, e.g. 1 or an atom, maps, tuples, etc--not just a variable, like x, y, or z. Here is how go1() works:
A.go1(%{a: 1 b: 2})
|-----+----|
|
| %{a: a} = %{a: 1 b: 2}
V
def go1(z = %{a: a}) do
The "parameter variable" is %{a: a}, and it gets matched to the function argument %{a: 1 b: 2}, which binds a to 1. Then, you might think that you get the pattern match: z = %{a: 1}, however, the pattern match %{a: a} = %{a: 1 b: 2} actually returns the right hand side:
iex(10)> %{a: a} = %{a: 1, b: 2}
%{a: 1, b: 2}
Therefore, you get the pattern match: z = %{a: 1, b: 2}. Here is another demonstration of that:
iex(13)> z = %{a: a} = %{a: 1, b: 2}
%{a: 1, b: 2}
iex(14)> a
1
iex(15)> z
%{a: 1, b: 2}
Here is how go2() works:
A.go1(%{a: 1 b: 2})
|-----+----|
|
| z = %{a: 1, b: 2}
V
def go2(%{a: a} = z)
z is the parameter variable and it gets matched to the function argument %{a: 1 b: 2}. The match z = %{a: 1 b: 2} returns the right hand side:
iex(10)> z = %{a: 1, b: 2}
%{a: 1, b: 2}
So, next you get the pattern match: %{a: a} = %{a: 1, b: 2}, which binds a to 1.
Therefore, all is consistent: with every pattern match, the pattern containing the variables is on the left of =, and the values are on the right side. If you are looking for a rule it's: in the parameter list for a function definition, the thing on the right of an = sign is the "parameter variable". The thing on the left is a pattern that will get matched after the "parameter variable" is matched to the function argument (or as you would say in other languages: "after the function argument is assigned to the parameter variable").