How to pattern match: %{ 1 => [ 2, 3 ] }

Hi,
i want pattern-match on map like this…

iex(1)> a = %{ 1 => [ 2, 3 ] }
%{1 => [2, 3]}

iex(2)> %{ { v, [a,b] } } = a
!!ERROR!!** (SyntaxError) iex:2: syntax error before: '}'

but never success, how to write correct pattern-match in there?
thanks

Logically you would think to:

iex> a = %{1 => [2,3]}
%{1 => [2, 3]}
iex> %{k => [v1, v2]} = a

But its not possible to match on variable keys. The error you will get with the above is:

** (CompileError) iex:2: cannot use variable k as map key inside a pattern. Map keys in patterns can only be literals (such as atoms, strings, tuples, etc.) or an existing variable matched with the pin operator (such as ^some_var)
    (stdlib 3.9.1) lists.erl:1263: :lists.foldl/3

You can match on the value and shape of a key such as:

iex> %{1 => [v1, v2]} = a
%{1 => [2, 3]}

The reasoning is that if the key is a variable, Elixir/Erlang would have to scan the entire map to see if any entries match and that is rarely what is intended. Additionally, such a variable match could match more than one map entry and the semantics of matching don’t implement a multiple match.

2 Likes

Yes, I know i can match with a known key
But what i want is to be able to dynamically know the value of that key :sweat_smile:

I guess i need hard code to do this, not using pattern-match :slight_smile:

Still thank you very much :slight_smile:

You will need to iterate over all keys and attempt to match on each of them yourself. The reasons being as I outlined above:

  1. More than one map entry may match
  2. Matching the way you want would require iterating over the whole map - which is not the contract for match/2.

In your own code you will still have to decide what to do if more than one map entry matches.

2 Likes

yes, i understand,
It seems as long as it is a pair of key-value,
We can’t use pattern-match to match it,

thank you :smiley: