I can't seem to find a way to pattern match on a map's key in a function head. Is there a way to do this? What I'm trying to do is run different code depending on whether a certain key already exists in a map or not (and also wanted to avoid if/else and the like)
This is what my code looks like
def my_func(key, %{key => _} = map), do: ...
which gives me this error
** (CompileError) illegal use of variable key inside map key match, maps can only match on existing variable by using ^key
Of course I also tried it using the ^
def my_func(key, %{^key => _} = map), do: ...
which then gives
** (CompileError) unbound variable ^key
I'm using elixir 1.3.1/erlang 19.0 x64 on a windows 8.1 machine.
Thanks for reading!
Best Answer
You can try several approaches depending on the specific problem and the Elixir version you're using:
Map pattern matching
If you can just pattern match with the key you need:
Then in IEx:
Also order of the clauses are important e.g. if you are trying to match
%{"b" => 2}
but you have the following map%{"a" => 1, "b" => 2}
, the key"a"
will match first, because is in the first clause:If you want to generate something for every key you can match, I recommend a different approach. For example, if you want to map a function to those keys:
So you would get the following:
Checking a given key exists (Elixir < 1.10)
You cannot pattern match a key to a variable. The problem is the compiler needs to generate code to search for something it doesn't know yet. When you pattern match you usually give the compiler some hints of what it'll receive. For keys in maps the hint is the key itself. In this case, even pointing that the first argument should be the key to look for, it is not enough for the compiler. So your approach should be to use an if statement:
Checking a given key exists (Elixir >= 1.10)
Elixir 1.10 adds the guard
is_map_key/2
that can be used to solve this problem finally!This will definitely solve the compilation issue :)
I hope this answers your question.