3

I am generating some functions in the module:

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

The issue is the generated function obviously accepts one single argument, namely a list of size 2:

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

The goal is to dynamically declare the function accepting two arguments. In ruby terminology, it would be to unsplat argument list.

Is there a possibility to accomplish this without pattern matching the resulting AST for {:do_it, blah, [[ list of arguments ]]} and flattening the list manually?

1 Answer 1

6

You can use Kernel.SpecialForms.unquote_splicing/1 to "splice" in the args list:

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]
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.