2016-10-25 77 views
3

我的模塊中有三個相同的方法,它們(幾乎)完全相同。我不是重複函數定義,而是試圖定義它們來保持代碼最小化和相同。Elixir - 通過元編程定義模塊中的函數

到目前爲止,我使用Code.eval_string已經試過:

defmodule MyModule do 
    Enum.each ~w(method1 method2 method3), fn method -> 
    @method method 

    Code.eval_string """ 
     def #{@method}(map) when is_map(map) do 
     do_map_stuff(:#{@method}, map) 
     end 

     def #{@method}(arg) do 
     do_other_stuff(:#{@method}, arg) 
     end 
    """ 
    end 

    ## Other Methods 

end 

但是,這將引發ArgumentError

Compiling 1 file (.ex) 
** (ArgumentError) cannot invoke def/2 outside module 
    (elixir) lib/kernel.ex:4297: Kernel.assert_module_scope/3 
    (elixir) lib/kernel.ex:3299: Kernel.define/4 
    (elixir) expanding macro: Kernel.def/2 
    nofile:1: (file) 

我認爲報價/引文結束可能是要走的路,但我不完全確定如何使用它們(我已經閱讀了Elixir網站上的Meta Guide)。

回答

1

這樣的事情?

defmodule MyModule do 
    def do_map_stuff(method, arg) do 
    IO.inspect([method, arg]) 
    end 

    Enum.each [:method1, :method2, :method3], fn method -> 
    def unquote(method)(map) when is_map(map) do 
     do_map_stuff(unquote(method), map) 
    end 

    def unquote(method)(arg) do 
     do_map_stuff(unquote(method), arg) 
    end 
    end 
end 
+1

我更新它使用原子而不是字符串,它更適合我的情況(也看起來更清潔和可讀!) – Sheharyar

相關問題