パターンマッチで遊んでいると、メソッドのパラメーターを空のマップに対してパターンマッチするのは簡単ではないことがわかりました。私はそれがこのような何かになるだろうと思った:
defmodule PatternMatch do
def modify(%{}) do
%{}
end
def modify(map) do
# expensive operation
%{ modified: "map" }
end
end
しかし、最初の関数句は任意のマップに一致するようです:
iex> PatternMatch.modify(%{a: "map"})
==> %{}
空のマップを確認する別の方法はありますか?
設計上はこのように機能しますが、確かに一見すると少し混乱する可能性があります。この機能により、すべてのキーを指定しなくても、パターンマッチングを使用してマップを分解できます。例えば:
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
@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
以下は、Kernel.match?/2
を使用してmap_size/1
が動作していることを示すiexの出力です。
iex(6)> Kernel.match?(map when map_size(map) == 1, %{})
false
iex(7)> Kernel.match?(map when map_size(map) == 1, %{foo: "bar"})
true
これまでに提供されたすべてのクールな回答に加えて、帽子または上矢印のように見える 単項ピン演算子 の使用を検討することもできます。関連するドキュメントに記載されているように、変数の接頭辞として使用して変数の値とパターンが一致するようにします。
変数を再バインドするのではなく、既存の変数の値とパターンマッチする場合は、ピン演算子^を使用します
次に例を示します。
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
どの方法を使用するかは、コードを読みやすくするための個人/組織の好みによって異なります。