如何“拼写”动态创建函数的函数参数

How to “splat” the function arguments for dynamically created function

我正在模块中生成一些函数:

defmodule M do
  funs = [do_it: [:arg1, :arg2]]

  Enum.each(funs, fn {name, args} ->
    args = Enum.map(args, & {&1, [], Elixir})
    def unquote(name)(unquote(args)),
      do: IO.inspect(unquote(args))
  end)
end

问题是生成的函数显然接受一个参数,即大小为 2 的列表:

▶ M.__info__(:functions) 
#⇒ [do_it: 1]

目标是动态声明接受两个参数的函数。在 ruby 术语中, 取消 参数列表。

是否有可能在不匹配 {:do_it, blah, [[ list of arguments ]]} 的结果 AST 模式并手动展平列表的情况下完成此操作?

您可以在 args 列表中使用 Kernel.SpecialForms.unquote_splicing/1 到 "splice":

defmodule M do
  funs = [do_it: [:arg1, :arg2], do_it: [:arg1, :arg2, :arg3]]

  Enum.each(funs, fn {name, args} ->
    def unquote(name)(unquote_splicing(args)), do: :ok
  end)
end
iex(1)> M.__info__(:functions)
[do_it: 2, do_it: 3]