【问题标题】:Pattern match function against empty map针对空地图的模式匹配功能
【发布时间】:2016-01-19 19:56:09
【问题描述】:

我正在玩模式匹配,我发现,将方法的参数与空映射进行模式匹配并不容易。我认为它会是这样的:

defmodule PatternMatch do
  def modify(%{}) do
    %{}
  end

  def modify(map) do
    # expensive operation
    %{ modified: "map" }
  end
end

但似乎第一个函数子句匹配任意映射:

iex> PatternMatch.modify(%{a: "map"})
==> %{}

还有其他方法可以检查空地图吗?

【问题讨论】:

  • 函数子句的顺序也会影响这个问题吗?我的意思是空映射是否总是匹配,因此需要成为最后一个函数子句?

标签: pattern-matching elixir


【解决方案1】:

除了到目前为止提供的所有酷答案之外,您还可以考虑使用看起来像帽子或上箭头的unary pin operator。如相关文档中所述,您可以使用它为变量添加前缀,以确保您对其值进行模式匹配:

当您想要对 现有变量的值,而不是重新绑定变量

以下是一个例子:

defmodule A do
  def determine_map_volume(some_map) do
    an_empty_map = %{}

    some_map
    |> case do
    ^an_empty_map -> :empty  # Application of pin operator
    _ -> :not_empty
    end
  end
end

您可以通过以下方式验证:

A.determine_map_volume(%{})
:empty
A.determine_map_volume(%{a: 1})
:not_empty

您打算使用哪种方法取决于您个人/组织对代码可读性的偏好。

【讨论】:

    【解决方案2】:

    除了@PatrickOscity 的答案(我将用于空地图)之外,您还可以使用map_size/1 保护来匹配具有多个键的地图:

    defmodule PatternMatch do
      def modify(map) when map_size(map) == 0 do
        %{}
      end
    
      def modify(map) when map_size(map) == 1 do
        #something else
      end
    
      def modify(map) do
        # expensive operation
        %{ modified: "map" }
      end
    end
    

    这是 iex 的输出,使用 Kernel.match?/2 显示 map_size/1 的实际效果:

    iex(6)> Kernel.match?(map when map_size(map) == 1, %{})
    false
    iex(7)> Kernel.match?(map when map_size(map) == 1, %{foo: "bar"})
    true
    

    【讨论】:

    • 不错的补充。小修正:我认为应该是when map_size(map) ... 而不是when map_size ...
    • 好发现!谢谢。
    【解决方案3】:

    它的设计是这样工作的,但不可否认,乍一看它可能有点令人困惑。此功能允许您使用模式匹配解构映射,而无需指定所有键。例如:

    iex> %{b: value} = %{a: 1, b: 2, c: 3}
    %{a: 1, b: 2, c: 3}
    
    iex> value
    2
    

    因此,%{} 将匹配任何地图。如果要匹配函数中的空映射,则必须使用保护子句:

    defmodule PatternMatch do
      def modify(map) when map == %{} do
        %{}
      end
    
      def modify(map) do
        # ...
      end
    end
    

    【讨论】:

    • 我在%{} 上进行了模式匹配,以告诉我的代码没有必要尝试在数据库中存储空地图......这就是所谓的错误。这让我很惊讶,因为我忘记了以前在书中读到的内容。这意味着 10 天内数据库中没有数据。幸运的是,这是一个开发设置
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-30
    • 2016-07-13
    • 2013-09-06
    相关资源
    最近更新 更多