Pattern matching 针对空映射的模式匹配函数
我在玩弄模式匹配,我发现,根据空映射模式匹配方法的参数并不容易。我以为会是这样的:Pattern matching 针对空映射的模式匹配函数,pattern-matching,elixir,Pattern Matching,Elixir,我在玩弄模式匹配,我发现,根据空映射模式匹配方法的参数并不容易。我以为会是这样的: defmodule PatternMatch do def modify(%{}) do %{} end def modify(map) do # expensive operation %{ modified: "map" } end end 但第一个function子句似乎匹配任意映射: iex> PatternMatch.modify(%{a: "map"}
defmodule PatternMatch do
def modify(%{}) do
%{}
end
def modify(map) do
# expensive operation
%{ modified: "map" }
end
end
但第一个function子句似乎匹配任意映射:
iex> PatternMatch.modify(%{a: "map"})
==> %{}
有没有其他方法可以检查空地图?这种方法是设计出来的,但必须承认,乍一看可能有点混乱。此功能允许您使用模式匹配来分解贴图,而无需指定所有关键点。例如:
iex> %{b: value} = %{a: 1, b: 2, c: 3}
%{a: 1, b: 2, c: 3}
iex> value
2
因此,%{}
将匹配任何映射。如果要匹配函数中的空映射,必须使用guard子句:
defmodule PatternMatch do
def modify(map) when map == %{} do
%{}
end
def modify(map) do
# ...
end
end
除了@PatrickOscity的答案(我会将其用于空地图)之外,您还可以使用一个守卫来匹配具有多个键的地图:
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使用内核.match?/2
的输出,以显示映射大小/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
除了迄今为止提供的所有酷答案之外,你也可以考虑使用看起来像帽子或上箭头点的东西。您可以使用它作为变量的前缀,以确保模式与其值匹配,如相关文档中所述: 当您要与图形匹配时,请使用pin运算符^ 现有变量的值,而不是重新绑定变量 以下是一个例子:
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
您打算使用哪种方法取决于您个人/组织对代码可读性的偏好。Nice addition。小更正:我认为它应该是
当地图大小(map).
而不是当地图大小…
很好的发现!谢谢。功能条款的顺序也会影响到这个问题吗?我的意思是一个空映射是否总是匹配的,因此需要成为最后一个函数子句?我在%{}
上进行了模式匹配,以告诉我的代码,在数据库中存储空映射时没有必要这样做。。。这就是所谓的bug。我很惊讶,因为我忘了我以前在书中读过的东西。这意味着10天内数据库中没有数据。幸运的是,这是一个开发设置