Ответ 1
Просто совпадающий шаблон с ключом, который вам нужен:
defmodule Test do
def my_func(%{"a" => value}), do: {:a, value}
def my_func(%{"b" => value}), do: {:b, value}
def my_func(_), do: :error
end
Затем в IEx:
iex(1)> Test.my_func(%{"a" => 1})
{:a, 1}
iex(2)> Test.my_func(%{"b" => 2})
{:b, 2}
Также важны порядок предложений. Например, если вы пытаетесь сопоставить %{"b" => 2}
, но у вас есть следующая карта %{"a" => 1, "b" => 2}
, ключ "a"
будет соответствовать первым, поскольку находится в первом разделе:
iex(3)> Test.my_func(%{"a" => 1, "b" => 2})
{:a, 1}
Если вы хотите сгенерировать что-то для каждого ключа, который вы можете сопоставить, я рекомендую другой подход. Например, если вы хотите сопоставить функцию с этими клавишами:
defmodule Test0 do
def my_op({"times_2", value}), do: {"times_2", value * 2}
def my_op({"times_3", value}), do: {"times_3", value * 3}
def my_op({key, value}), do: {key, value}
def my_func(m) do
Enum.map(m, &my_op/1) |> Enum.into(%{})
end
end
Итак, вы получите следующее:
iex(1)> Test0.my_func(%{"times_2" => 2, "times_3" => 3, "whatever" => 42})
%{"times_2" => 4, "times_3" => 9, "whatever" => 42}
Обновить в соответствии с комментариями для этого ответа
Вы не можете сопоставить шаблон переменной с переменной. Проблема заключается в том, что компилятор должен генерировать код для поиска того, чего он еще не знает. Когда вы сопоставляете шаблон, вы обычно даете компилятору некоторые намеки на то, что он получит. Для ключей в картах подсказка - это ключ. В этом случае, даже указывая, что первым аргументом должен быть ключ к поиску, его недостаточно для компилятора. Поэтому ваш подход должен заключаться в использовании оператора if:
defmodule Test2 do
def my_func(k, m) do
if Map.haskey?(k, m), do: warning(k, m), else: foo(k, m)
end
def warning(k, m) do
#Warning
m
end
# In this function you could apply the pattern matching
# described in the first part of this answer.
def foo(k, m) do
value = # do something
%{m | key => value}
end
end
Надеюсь, это ответит на ваш вопрос.