在编写函数时,我正在使用参数匹配:
def process_thing( %{} = thing )
我期待thing
是一张地图,并且是可枚举的。不幸的是,这个参数列表也匹配指定为~r/regex/
的正则表达式,而正则表达式(虽然它对is_map(~r/thing/)
返回true)不是可枚举的。
我如何制作这个函数定义,以便只将地图 - 或理想情况下的可枚举的东西 - 分派给这个函数?
答案 0 :(得分:5)
在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: ...
...
如果您需要支持所有枚举(可能更容易提供有关您的用例的更多信息的好建议),您可以随时使用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
),解决它的一种方法是首先匹配你不想要匹配,以便让它们脱离(并根据需要处理它们):
def process_thing(%{__struct__: _}), do: # bad things here, we don't like structs
def process_thing(%{} = thing), do: # hey, that's a map now!