2017-06-29 26 views
1

我有一个格式为{:task, function_name, description}的元组列表,我想生成一个调用元组中定义的函数来覆盖值的函数。Elixir元编程:将函数调用列表注入到函数体中

我生成的函数应该是这样的:

def run(val) do 
    val = do_something(val) 
    val = do_something_else(val) 
    ... 

    val 
end 

这里是我当前的代码:

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 

但是,生成以下功能:

def(run(val)) do 
    [val = it_adds_five(val), val = it_adds_ten(val)] 
    val 
end 

正如你所看到的,我的函数调用在列表中,只有最后一个函数调用被应用。当我将2的值传递给run函数时,我得到了12

回答

2

您可以使用Kernel.SpecialForms.unquote_splicing/1而不是Kernel.SpecialForms.unquote/1在AST节点列表中“拼接”。

更改:

def run(val) do 
    unquote(iteration) 
    val 
end 

def run(val) do 
    unquote_splicing(iteration) 
    val 
end 

生成此AST:

def(run(val)) do 
    val = bar(val) 
    val = foo(val) 
    val 
end 

@steps [ 
    {:task, :foo, ""}, 
    {:task, :bar, ""}, 
] 
+1

WOW。这解决了它!非常感谢您的快速回复:)您节省了我的一天! – Phillipp

+0

@mudasobwa感谢您添加链接。 :) – Dogbert