leifericf

leifericf

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
1
iex(2)> a = 2
2

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

Eshell V8.3  (abort with ^G)
1> A = 1.
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
1
iex(2)> [^a, 2, 3] = [1, 2, 3]
[1, 2, 3]
iex(3)> a = 2
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.

Most Liked

peerreynders

peerreynders

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:

Last Post!

leifericf

leifericf

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

Where Next?

Popular in Discussions Top

jesse
Hi everyone, I hesitated to post this here because I don’t want you to think I’m spamming, but I’ve been working on a Platform-as-a-Serv...
New
rower687
Hi all, I’ve been reading a lot about the “let it crash” term and how supervising processes and the whole messaging passing make an elixi...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 40082 209
New
opsb
We’re considering our architecture from a viewpoint of scaling our traffic heavily over the next 6 months. Our current deployment is runn...
New
cvkmohan
The upcoming Phoenix 1.6 release looks very interesting. Became a habit to watch the commits - and - what they are bringing in. phx.gen...
New
paulanthonywilson
I like Umbrella projects and pretty much always use them for personal Elixir stuff, especially Nerves things. But I don’t think this is ...
New
matthias_toepp
I’d love to hear what people think about Wisp, the new Gleam web framework started by Gleam’s primary creator Louis Pilfold. Gleam, alon...
New

Other popular topics Top

KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 36689 110
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New