如何检查协议是否已实现?

16

我想知道是否有一种方法可以问 Elixir,这个对象是否实现了那个协议,类似于 obj |> implements(Enumerable) 这样的方式?

基本上,我需要区分结构体和哈希表。我目前有一个解决方案,但它有点丑陋:

try
  obj |> Enum.each ...
rescue 
  e in Protocol.UndefinedError -> obj |> Maps.keys ...
end

上述方法可行,但我更倾向于使用模式匹配,如下:

cond do
  obj |> is_implemented(Enumerable) -> ...
  _ -> ...
end

我是否漏掉了什么?我能否明确地检查对象是否实现了所需协议?

1个回答

23
你可以检查Protocol.impl_for(term)是否返回nil:
iex(1)> Enumerable.impl_for []
Enumerable.List
iex(2)> Enumerable.impl_for {}
nil
iex(3)> Enumerable.impl_for MapSet.new
Enumerable.MapSet

3
好的,谢谢。我想知道为什么这个链接 http://elixir-lang.org/docs/stable/elixir/Enumerable.html 上缺失了这个内容。 - Aleksei Matiushkin
可能是因为 https://github.com/elixir-lang/elixir/blob/d02be44dd5deb763e5a0eb03f3c716506d781d08/lib/elixir/lib/protocol.ex#L430。 - Dogbert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接