Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elixir macros: how to define function with dynamic arity

Tags:

macros

elixir

refer this post: How to create a dynamic function name using Elixir macro?.

The post above asked how to use macro to generate function without arguments, but I wonder how to generate functions with some arguments ?

assume there is a macro warp, I could just write code like:

warp fun, [args], :ok

and then it generate code like:

fun(args), do: :ok
like image 263
keroro520 Avatar asked Oct 10 '15 06:10

keroro520


People also ask

What is arity in Elixir?

Arity means how many input parameters Elixir function has. This post is part of the functional language series, and it is based on the remarkable book Elixir In Action by Sasa Juric. In Elixir, function uniqueness is defined with: Module name.05-Jun-2020.

How will you explain macros in Elixir?

Macros are compile-time constructs that are invoked with Elixir's AST as input and a superset of Elixir's AST as output. The macro receives the representation of the code given as argument, while a function receives the result of the code given as argument. A macro must return a superset of the code representation.

When should I use macros in Elixir?

Elixir already provides mechanisms to write your everyday code in a simple and readable fashion by using its data structures and functions. Macros should only be used as a last resort. Remember that explicit is better than implicit. Clear code is better than concise code.


1 Answers

If you want to generate a dynamic list of arguments, you need to use unquote_splicing, like this:

defmacro warp(name, argument_names, code) do
  quote do
    def unquote(name)(unquote_splicing(argument_names)) do
      unquote(code)
    end
  end
end

Then later:

warp :foo, [a, b], {:ok, a, b}

which generates:

def foo(a, b), do: {:ok, a, b}

if you call that it will produce:

foo(1, 2)
# {:ok, 1, 2}

You can also define the macro like this without unquote_splicing and just pass down the combined name and arguments to def:

defmacro warp(name_and_args, do: code) do
  quote do
    def unquote(name_and_args) do
      unquote(code)
    end
  end
end

This means you need to invoke warp like you would invoke def, for example:

warp foo(a, b), do: {:ok, a, b}
like image 86
Patrick Oscity Avatar answered Oct 12 '22 05:10

Patrick Oscity