Reputation: 1445
I have a list of tuples with the format {:task, function_name, description}
and I want to generate a function that calls the functions defined in the tuples to override a value.
My generated function should look like:
def run(val) do
val = do_something(val)
val = do_something_else(val)
...
val
end
Here is my current code:
defmacro __before_compile__(env) do
steps = Module.get_attribute(env.module, :steps) |> Enum.reverse
iteration = Enum.map steps, fn {:task, func, _} ->
quote do
val = unquote(func)(val)
end
end
ast = quote do
def run(val) do
unquote(iteration)
val
end
end
ast
end
But that generates the following function:
def(run(val)) do
[val = it_adds_five(val), val = it_adds_ten(val)]
val
end
As you can see, my function calls are inside a list and only the last function call is applied. When I pass the value 2
into the run
function, i get 12
back.
Upvotes: 1
Views: 383
Reputation: 222118
You can use Kernel.SpecialForms.unquote_splicing/1
instead of Kernel.SpecialForms.unquote/1
to "splice" in a list of AST nodes.
Changing:
def run(val) do
unquote(iteration)
val
end
to
def run(val) do
unquote_splicing(iteration)
val
end
Generates this AST:
def(run(val)) do
val = bar(val)
val = foo(val)
val
end
for
@steps [
{:task, :foo, ""},
{:task, :bar, ""},
]
Upvotes: 2