Question: Why variables don't rebind in pattern matching?

Why variable a is not rebinding here, like we do in the elixir

iex> a = 1
iex> a =2
iex> [a, a] = [1, 2] # Fail

Could some experts break this puzzle ?
What’s happening in the pattern matching here?

Maybe because your pattern match doesn’t make any sense, how can a be matched to both 1 and 2? If you want to match the same value, it has to be matched to the same result:

[a, a] = [1, 1]

@D4no0
Could you please elaborate how pattern checking works here?
What’s happening when we use same variable in a list? Why is this not rebinding?

This is explained here:

If the same variable appears twice in the same pattern, then they must be bound to the same value:

iex> {x, x} = {1, 1}
{1, 1}
iex> {x, x} = {1, 2}
** (MatchError) no match of right hand side value: {1, 2}
9 Likes

Also, some more historical context as of why it came to be this way:

  • this is the way pattern-matching works in Erlang (and Elixir is basically Erlang)
  • I suspect that Erlang borrowed it from Prolog which works the same way

Erlang:

1> {X, X} = {1, 2}.
** exception error: no match of right hand side value {1,2}
2> {X, X} = {1, 1}.
{1,1}

Prolog

| ?- {X, X} = {1, 2}.

no
| ?- {X, X} = {1, 1}.

X = 1

yes
3 Likes

The important thing here is that this has nothing to do with rebinding, the example [a, a] = [1, 2] is a invariant.

Matching is treated as a single operation, a pattern where a can be both 1 and 2 doesn’t exist, so it is not possible to match, as opposed to the author thinking that a will be matched to 1 first, then rebinded to 2 afterwards.

2 Likes

Adding my fifty cents here, when you do [a, a] = some_list_here, you also semantically tell to elixir that you have a list of exactly two elements and both elements are equal, after this condition satisfy on the right side of pattern then occur the binding.

something similar occurs in function definitions where have two arguments with same name:

defmodule MyBool do
	def exactly_equals(x, x), do: true
	def exactly_equals(_, _), do: false
end
2 Likes