我有一个模块,可以通过以下方式将外部调用动态路由到其自身的功能:
L1 55.596893310546875
L2 2.15625
L3 68.87890625
模块已成功编译,并且defmodule A do
defmacro call(name) do
quote do
fun = & unquote(:"A.#{name}")(&1)
fun.(:foo)
end
end
def test(param), do: IO.inspect(param, label: "test")
end
#⇒ {:module, A, ..., {:test, 1}}
在那里。
A.test/1
现在,我尝试将其称为:
A.test :foo
#⇒ test: :foo
这种动态呼叫分配有什么问题,为什么错误消息与现实矛盾呢?
答案 0 :(得分:2)
该错误消息具有误导性。 & unquote(:"A.#{name}")(&1)
将在当前范围内调用一个名为A.test
的函数,而不是模块test/1
的{{1}}函数:
A
输出:
defmodule A do
defmacro call(name) do
quote do
fun = & unquote(:"A.#{name}")(&1)
fun.(:foo)
end
end
def unquote(:"A.test")(param), do: IO.inspect(param, label: "!!!")
end
defmodule B do
require A
import A
def test, do: A.call(:test)
end
B.test
要使其调用模块!!!: :foo
的{{1}}函数,可以执行test/1
:
A
输出:
& A.unquote(:"#{name}")(&1)