首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在灵丹妙药中如何对函数头中的映射键进行模式匹配

在灵丹妙药中如何对函数头中的映射键进行模式匹配
EN

Stack Overflow用户
提问于 2016-07-06 09:53:16
回答 1查看 21.6K关注 0票数 22

我似乎找不到一种方法来匹配地图的键在一个函数头。有办法这样做吗?我要做的是运行不同的代码,具体取决于某个键是否已经存在于映射中(同时也希望避免if/else等)

这就是我的代码

代码语言:javascript
复制
def my_func(key, %{key => _} = map), do: ...

这给了我这个错误

** (CompileError)在映射密钥匹配中非法使用变量密钥,映射只能使用^key匹配现有变量

当然,我也使用^进行了尝试

代码语言:javascript
复制
def my_func(key, %{^key => _} = map), do: ...

然后给出

** (CompileError)未绑定变量^key

我在Windows8.1机器上使用了灵丹妙药1.3.1/Erlang19.0 x64。感谢您的阅读!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-07-06 10:31:30

您可以尝试几种方法,具体取决于具体问题和您正在使用的药物版本:

  • 地图模式匹配
  • 检查给定的密钥(Elixir < 1.10)
  • 检查给定的密钥( >= 1.10)

地图模式匹配

如果您只需使用所需的键进行模式匹配:

代码语言:javascript
复制
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中:

代码语言:javascript
复制
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"将首先匹配,因为在第一个子句中:

代码语言:javascript
复制
iex(3)> Test.my_func(%{"a" => 1, "b" => 2})
{:a, 1}

如果您想要为您可以匹配的每个键生成某种内容,我建议使用不同的方法。例如,如果要将函数映射到这些键:

代码语言:javascript
复制
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

这样你就可以得到以下信息:

代码语言:javascript
复制
iex(1)> Test0.my_func(%{"times_2" => 2, "times_3" => 3, "whatever" => 42})
%{"times_2" => 4, "times_3" => 9, "whatever" => 42}

检查给定的密钥(Elixir < 1.10)

不能将键与变量匹配。问题是编译器需要生成代码来搜索它还不知道的东西。当模式匹配时,通常会给编译器一些提示,说明它会收到什么。对于映射中的键,提示本身就是键本身。在这种情况下,即使指出第一个参数应该是查找的关键,这对编译器来说还是不够的。因此,您的方法应该是使用if语句:

代码语言:javascript
复制
defmodule Test1 do
  def my_func(k, m) do
    if Map.has_key?(k, m) do
      ... do something when key is found ...
    else
      ... do something when key is not found ...
    end
  end
end

检查给定的密钥( >= 1.10)

灵丹妙药1.10增加了护卫is_map_key/2,最终可以用来解决这个问题!

代码语言:javascript
复制
defmodule Test2 do
  def my_func(key, map) when is_map_key(map, key) do
    ... key is found ...
  end

  def my_func(_, _) do
    ... key is not found ...
  end
end

这肯定会解决编译问题:)

我希望这能回答你的问题。

票数 28
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38221126

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档