Elixir: pattern matching works differently for tuples and maps

前端 未结 2 1406
孤城傲影
孤城傲影 2021-02-07 14:44

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:

<         


        
2条回答
  •  [愿得一人]
    2021-02-07 15:05

    maps, the main key-value store in Elixir, have an interesting capability that sets them apart from other data structures with regards to pattern-matching.

    A map can actually pattern-match on just a subset of a value. The key(s) in the pattern have to exist in the match, but the two structures don’t have to mirror each other in the same way a list or a tuple has to. For example:

    iex(1)> [a, b] = [1, 2, 3]
    ** (MatchError) no match of right hand side value: [1, 2, 3]
    
    iex(1)> {a, b} = {1, 2, 3}
    ** (MatchError) no match of right hand side value: {1, 2, 3}
    
    iex(1)> %{:a => one} = %{:a => 1, :b => 2, :c =>3}
    %{a: 1, b: 2, c: 3}
    iex(2)> one
    1
    iex(3)> %{:a => one, :c => three} = %{:a => 1, :b => 2, :c =>3}
    %{a: 1, b: 2, c: 3}
    iex(4)> three
    3
    iex(5)> one
    1
    iex(6)> %{} = %{:a => 1, :b => 2, :c =>3}
    %{a: 1, b: 2, c: 3}
    iex(7)> %{:d => four} = %{:a => 1, :b => 2, :c =>3}
    ** (MatchError) no match of right hand side value: %{a: 1, b: 2, c: 3}
    
    iex(8)> %{:a => one, :d => four} = %{:a => 1, :b => 2, :c =>3}
    ** (MatchError) no match of right hand side value: %{a: 1, b: 2, c: 3}
    

    We can see that neither the list nor the tuple matches if the data structure of the pattern is different to the data structure of the match, namely the size. Whereas this is not the case for the map. Because the key is present in both the pattern and the match then the match is successful, regardless of the different sizes of the pattern and the match. An empty map will also match.

    However the match will not be successful if the key in the pattern is not in the match. This is also the case even if there are matching keys. So any key used in the pattern has to be present in the match.

    You will see this sort of matching extensively in Phoenix Framework to pick up only the necessary params from request.

    Source: - Notes on Elixir: Pattern-Matching Maps

提交回复
热议问题