如何使用 Kernel.apply 作为宏功能

How can I use Kernel.apply for macro function

Kenel.apply/3 function elixir 无法调用宏定义的函数。

示例,

defmodule Hoge1 do
  for fun_name <- [:foo, :bar] do
    defmacro unquote(fun_name)(arg) do
      apply(Hoge2, unquote(fun_name), [arg])
    end
  end
end

defmodule Hoge2 do
  for fun_name <- [:foo, :bar] do
    defmacro unquote(fun_name)(arg) do
      IO.puts "hoge2"
    end
  end
end

以上情况,如果我调用 Hoge1.foo,则会引发错误。 (undefined function: Hoge2.foo/1)

我可以直接打电话给Hoge2.foo/1。 (输出"hoge2")

我可以用内核调用吗?apply/3 ?

apply 仅适用于函数,不适用于宏。首先检查你是否真的需要宏,因为很多问题可以(并且应该)只用函数来解决。在这种情况下,您可以只使用 def 代替 defmacro:

defmodule Hoge1 do
  for fun_name <- [:foo, :bar] do
    def unquote(fun_name)(arg) do
      apply(Hoge2, unquote(fun_name), [arg])
    end
  end
end

defmodule Hoge2 do
  for fun_name <- [:foo, :bar] do
    def unquote(fun_name)(arg) do
      IO.puts "hoge2"
    end
  end
end

如果您的解决方案严格需要宏,您可以直接生成宏调用而不是使用 apply:

Hoge2.unquote(fun_name)(arg)

要使 Hoge2 宏可用于 Hoge1,您还需要在 Hoge1 中要求 Hoge2。完整的解决方案如下所示

defmodule Hoge2 do
  for fun_name <- [:foo, :bar] do
    defmacro unquote(fun_name)(arg) do
      IO.puts "hoge2"
    end
  end
end

defmodule Hoge1 do
  require Hoge2

  for fun_name <- [:foo, :bar] do
    defmacro unquote(fun_name)(arg) do
      Hoge2.unquote(fun_name)(arg)
    end
  end
end