正则表达式和地图参数匹配

Regex and Map argument matching

在编写函数时,我正在使用参数匹配,如下所示:

def process_thing( %{} = thing )

我希望 thing 是一个 Map,并且是可枚举的。不幸的是,这个参数列表也匹配指定为 ~r/regex/ 的正则表达式,并且正则表达式(尽管它 returns 对于 is_map(~r/thing/) 为真)不是可枚举的。

我如何设计这个函数定义,以便只有映射——或者理想情况下,可枚举的东西——被分派到这个函数?

无法匹配 Enumerable。如果您只接受地图,那么您可以使用 is_map/1 内置函数:

def process_thing(thing) when is_map(thing) do
   ...
end

另一种方法是检查您期望和支持的所有数据类型:

def process_thing(thing) when is_map(thing) or is_list(thing), do: ...
def process_thing(%MapSet{}), do: ...
...

如果你需要支持 all 可枚举(也许提供更多关于你的用例的信息会更容易给出好的建议),你总是可以使用 Protocol.assert_impl!/2 :

def process_thing(thing) when is_map(thing) or is_list(thing), do: ...
def process_thing(%{__struct__: struct}) do
  assert_impl!(Enumerable, struct)
end

并处理Protocol.assert_impl!/2可能出现的故障。我不确定这个实现是否是防弹的,而且可能有更简洁的方法来实现它。 :)

还有一件事:如果你想在地图上匹配而不是在结构上匹配(比如Regex),解决它的一种方法是首先匹配你不要的东西t 想要匹配,这样你就可以将它们移开(并根据需要处理它们):

def process_thing(%{__struct__: _}), do: # bad things here, we don't like structs
def process_thing(%{} = thing), do: # hey, that's a map now!