First encounter with variable rebinding in pattern matching

As I’m currently in the early stages of learning Elixir, having learned Erlang first, I’m encountering some curiosities and confusions. I thought I’d share them. Here is the first such topic.

This is explained in more detail on pages 15-19 in Programming Elixir.

In Elixir, we can do this:

Interactive Elixir (1.6.5) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> a = 1
iex(2)> a = 2

If we try the same thing in Erlang, this happens:

Eshell V8.3  (abort with ^G)
1> A = 1.
2> A = 2.
** exception error: no match of right hand side value 2

When I first encountered this behaviour in Elixir, my immediate thought was something like: “Huh! That’s odd. I thought variables were inmmutable in Elixir, as in Erlang.”

This was a bit confusing for me, for two reasons:

  • The behavior in the REPL differed from Erlang.
  • This feature of Elixir gives the immediate impression of mutable variables.

Then I noticed that variables in Elixir bind once per match. Is this also the case for Erlang outside of the REPL? Now I’m thinking of matches sort of like their own local scopes.

Back in Elixir, we can also use the pin operator:

Interactive Elixir (1.6.5) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> a = 1
iex(2)> [^a, 2, 3] = [1, 2, 3]
[1, 2, 3]
iex(3)> a = 2
iex(4)> [^a, 2] = [1, 2]
** (MatchError) no match of right hand side value: [1, 2]

The pin operator, I think of as “extending the scope” out of the current match; sort of like lexical scoping, where the innermost scope (the current match) is searched first and ^ moves us to the outer scope.

I’m not sure if this is the correct way of thinking about it, though.

To me, Elixir allows rebinding (i.e. the values are immutable) while Erlang does not. Pinning is necessary to suppress the default rebind behaviour.

See also:


@peerreynders - Thanks for the link! That is a very thorough and well-written article.