lei*_*ifg 45 elixir pattern-matching
我正在玩模式匹配,我发现,将方法的匹配参数与空映射进行模式化并不容易.我认为它会是这样的:
defmodule PatternMatch do
def modify(%{}) do
%{}
end
def modify(map) do
# expensive operation
%{ modified: "map" }
end
end
Run Code Online (Sandbox Code Playgroud)
但似乎第一个函数子句匹配任意映射:
iex> PatternMatch.modify(%{a: "map"})
==> %{}
Run Code Online (Sandbox Code Playgroud)
还有另一种检查空地图的方法吗?
Pat*_*ity 77
它通过设计以这种方式工作,但不可否认,乍一看它可能有点令人困惑.此功能允许您使用模式匹配来解构地图,而无需指定所有键.例如:
iex> %{b: value} = %{a: 1, b: 2, c: 3}
%{a: 1, b: 2, c: 3}
iex> value
2
Run Code Online (Sandbox Code Playgroud)
因此,%{}将匹配任何地图.如果要匹配函数中的空映射,则必须使用guard子句:
defmodule PatternMatch do
def modify(map) when map == %{} do
%{}
end
def modify(map) do
# ...
end
end
Run Code Online (Sandbox Code Playgroud)
Gaz*_*ler 25
除了@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
Run Code Online (Sandbox Code Playgroud)
以下是来自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
Run Code Online (Sandbox Code Playgroud)
除了到目前为止提供的所有很酷的答案之外,您还可以考虑使用一元 pin 运算符看起来像帽子或上箭头点的一元您可以使用它来为变量添加前缀,以确保您对其值进行模式匹配,如相关文档中所述:
\n\n\n\n\n当您想要针对现有变量\xe2\x80\x99s 值进行模式匹配而不是重新绑定变量时,请使用 pin 运算符 ^
\n
下面是一个例子:
\n\ndefmodule A do\n def determine_map_volume(some_map) do\n an_empty_map = %{}\n\n some_map\n |> case do\n ^an_empty_map -> :empty # Application of pin operator\n _ -> :not_empty\n end\n end\nend\nRun Code Online (Sandbox Code Playgroud)\n\n您可以按如下方式验证:
\n\nA.determine_map_volume(%{})\n:empty\nA.determine_map_volume(%{a: 1})\n:not_empty\nRun Code Online (Sandbox Code Playgroud)\n\n您打算使用哪种方法取决于您个人/组织对代码可读性的偏好。
\n| 归档时间: |
|
| 查看次数: |
10959 次 |
| 最近记录: |