我有以下代码:
defprotocol Reversible do
@doc "Reverses data structure"
def reverse(term)
end
defimpl Reversible, for: [List, Map] do
def reverse(term), do: Enum.reverse(term)
end
它工作正常,但我想以某种方式列出所有可枚举的类型,并在其他地方使用它们。
所以我试着这样做:
# constants.ex
defmodule Constants do
@enumerables [List, Map]
def enumerables, do: @enumerables
end
# reversible.ex
import Constants, only: [enumerables: 0]
defprotocol Reversible do
def reverse(term)
end
defimpl Reversible, for: enumerables() do
def reverse(term), do: Enum.reverse(term)
end
我有一个错误:
== Compilation error in file lib/reversible.ex ==
** (FunctionClauseError) no function clause matching in Module.concat/2
The following arguments were given to Module.concat/2:
# 1
Reversible
# 2
[List, Map]
(elixir) lib/module.ex:562: Module.concat/2
lib/reversible.ex:8: (file)
(elixir) lib/kernel/parallel_compiler.ex:121:
anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1
如何解决这个问题?
答案 0 :(得分:4)
defimpl
检查for
参数at compile time(宏参数)and if it's a list, it recurses over all items of the list的值。由于您的变量不是文字列表,defimpl
不会将其视为列表。
您可以通过迭代列表并自己调用defimpl
来解决此问题:
# constants.ex
defmodule Constants do
@enumerables [List, Map]
def enumerables, do: @enumerables
end
# reversible.ex
defprotocol Reversible do
def reverse(term)
end
for enumerable <- Constants.enumerables do
defimpl Reversible, for: enumerable do
def reverse(term), do: Enum.reverse(term)
end
end
测试:
$ iex -S mix
iex(1)> Reversible.reverse [1, 2, 3]
[3, 2, 1]
iex(2)> Reversible.reverse %{1 => 2, 3 => 4}
[{3, 4}, {1, 2}]