我有一个项目,需要定义一些名称不同但定义完全相同的协议。
我尝试用use/2
来做到这一点,但是没有运气:它不起作用,从__using__/1
进行的定义不会出现在结果协议中:
defmodule Action do
defmacro __using__(_) do
quote do
def run(tool)
end
end
end
defprotocol Actions.ShowId do
use Action
end
defmodule Tools.SimpleRelay do
defstruct [:id]
defimpl Actions.ShowId do
def run(%Tools.SimpleRelay{id: id}), do: IO.puts(inspect(id))
end
end
关于具有协议实现定义的结构,我得到:
warning: module Actions.ShowId is not a behaviour (in module Actions.ShowId.Tools.SimpleRelay)
iex:8: Actions.ShowId.Tools.SimpleRelay (module)
如果我尝试使用它:
iex(6)> relay = struct(Tools.SimpleRelay, id: "ALongStringId")
%Tools.SimpleRelay{id: "ALongStringId"}
iex(7)> Actions.ShowId.run(relay)
** (UndefinedFunctionError) function Actions.ShowId.run/1 is undefined or private
Actions.ShowId.run(%Tools.SimpleRelay{id: "ALongStringId"})
是错误还是目的?还是只是我的定义不正确?
我曾尝试在elixirforum上问同样的问题(并将此任务背景张贴在此),到目前为止,我唯一的建议是这是一个错误。在打开问题之前,我想澄清一下它确实是一个错误。
谢谢!
Kernel.defprotocol/2
委派给Kernel.defprotocol/2
,然后通过取消导出Protocol.__protocol__/2
并导入Protocol.__protocol__/2
来依次委派redefines def/2
。在您的宏上下文中,def/2
宏指的是导入的ATM Kernel.def/2
,它破坏了所需的行为。
我不确定这是否是错误,但是您可以通过使用FQN调用Protocol.def/1
明确地来轻松解决它。
def