2016-10-25 2 views
3

제 모듈에는 세 가지 동일한 메소드가 있습니다 (거의 동일합니다). 함수 정의를 반복하는 대신 코드를 최소한으로 유지하고 모든 코드를 동일하게 유지하기 위해 정의하려고합니다.Elixir - 메타 프로그래밍을 사용하여 모듈에서 함수 정의하기

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 발생 :

은 지금까지 나는 Code.eval_string를 사용하려고했습니다

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

관련 문제