Elixir宏:如何用动态arity定义函数

ker*_*520 11 macros elixir

参考这篇文章:如何使用Elixir宏创建动态函数名称?.

上面的帖子询问如何使用宏来生成没有参数的函数,但我想知道如何用一些参数生成函数?

假设有一个宏warp,我可以写代码如下:

warp fun, [args], :ok
Run Code Online (Sandbox Code Playgroud)

然后它生成如下代码:

fun(args), do: :ok
Run Code Online (Sandbox Code Playgroud)

Pat*_*ity 13

如果要生成动态的参数列表,则需要使用unquote_splicing如下:

defmacro warp(name, argument_names, code) do
  quote do
    def unquote(name)(unquote_splicing(argument_names)) do
      unquote(code)
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

然后

warp :foo, [a, b], {:ok, a, b}
Run Code Online (Sandbox Code Playgroud)

产生

def foo(a, b), do: {:ok, a, b}
Run Code Online (Sandbox Code Playgroud)

如果你打电话说它会产生

foo(1, 2)
# {:ok, 1, 2}
Run Code Online (Sandbox Code Playgroud)

你也可以不用这样定义宏unquote_splicing,只需传递组合的名称和参数def:

defmacro warp(name_and_args, do: code) do
  quote do
    def unquote(name_and_args) do
      unquote(code)
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

这意味着您需要warp像调用一样调用def,例如:

warp foo(a, b), do: {:ok, a, b}
Run Code Online (Sandbox Code Playgroud)