Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elixir: pattern matching works differently for tuples and maps

In Elixir, if I try to pattern match the following two tuples:

{a} = {1, 2}

I get a match error. But if I do the same for two maps:

%{x: a} = %{x: 1, y: 2}

It works fine, and a binds to 1. I can see why matching the two tuples gave an error, but why did matching the maps not give an error?

like image 887
tldr Avatar asked May 16 '14 05:05

tldr


1 Answers

In the first example you are attempting to match a single element tuple against a two-element tuple. In the second example you are matching on the :x key in both the left and right maps.

EDIT: I should clarify the rules around data structures and pattern matching in Elixir.

When matching on tuples, you need to provide a pattern which matches the entire tuple structure. You can use _, which is the "catch-all" pattern, but you'll still need to provide it for all elements of the tuple. When matching on lists, you must match on either all elements when using the [a, b, c] = [1, 2, 3] syntax, or on the head and tail, using the [h|t] = [1, 2, 3] syntax. When matching maps though, you can match on one or more keys in the map, which gives you the %{a: b} = %{a: :foo, b: :bar} syntax.

The semantics are a bit different between data structures, but are fairly common sense. The tuple rule exists because two tuples cannot be the same unless they have the same number of elements, a list has the same limitation, but because of the semantics of lists, accessing the head element of the list is the most common operation when working with them, hence the [h|t] syntax. Maps however can match based on specific keys, so the number of elements are irrelevant, as long as both sides of the match contain the same key, and optional pattern for the value, then it's a successful match.

like image 133
bitwalker Avatar answered Oct 26 '22 07:10

bitwalker