Define Dynamic Functions with Dynamic Arguments (Arity) using Elixir Macros

Mustafa Turan
ElixirLabs
Published in
1 min readAug 27, 2016

--

There are two ways of dynamic function creation with arity using Elixir Macros. For both of the ways, the first thing is creating dynamic args:

defp create_args(_, 0),
do: []
defp create_args(fn_mdl, arg_cnt),
do: Enum.map(1..arg_cnt, &(Macro.var (:"arg#{&1}"), fn_mdl))
Image Credit: kingofwallpapers.com

First way is creating function without any arguments with a simple unquote do yield and then putting arguments inside the non-argumented function using `Macro.prewalk` or `Macro.postwalk`:

defmacro dynamic_fn_without_arity(fn_name) do
quote do
# We can specify documentation for the function
@doc false
def unquote(fn_name)() do
# IO.inspect(arg1)
# IO.inspect(arg2)
end
end
end
## Usage
fn_name = :some_new_fn
fn_args = create_args(SomeModule, 2)
ast = dynamic_fn_without_arity(fn_name)
# Here we are injecting args to our dynamic function
Macro.postwalk(ast, fn
({ast_fn_name, context, []}) when ast_fn_name == fn_name ->
{fn_name, context, fn_args}
(other) -> other
end)

Second way of dynamic function creation with arity is `unquote_splicing` function:

defmacro dynamic_fn_with_arity(fn_name, fn_args) do
quote do
# We can specify documentation for the function
@doc false
def unquote(fn_name)(unquote_splicing(fn_args)) do
# IO.inspect(arg1)
# IO.inspect(arg2)
end
end
end
## Usage
fn_name = :some_new_fn
fn_args = create_args(SomeModule, 2)
dynamic_fn_with_arity(fn_name, fn_args)

--

--

Mustafa Turan
ElixirLabs

Go, Elixir, Ruby, Software Architecture, Microservices