2015-10-10 13 views
9

odsyłają ten wpis: How to create a dynamic function name using Elixir macro?.Makra eliksirów: jak zdefiniować funkcję z dynamicznym aritem

Post powyżej zapytał, jak używać makra do generowania funkcji bez argumentów, ale zastanawiam się, jak wygenerować funkcje z pewnymi argumentami?

zakładają tam jest makro warp, mogę tylko napisać kod jak:

warp fun, [args], :ok 

a następnie wygenerować kod jak:

fun(args), do: :ok 
+0

Ja na tyle ciężko, aby znaleźć dokumenty na temat'unquote_splicing'. Zmiana tytułu może pomóc przyszłym pracownikom Google, takim jak ja. – nicooga

Odpowiedz

9

Jeśli chcesz wygenerować dynamiczną listę argumentów trzeba użyć unquote_splicing tak:

defmacro warp(name, argument_names, code) do 
    quote do 
    def unquote(name)(unquote_splicing(argument_names)) do 
     unquote(code) 
    end 
    end 
end 

Później

warp :foo, [a, b], {:ok, a, b} 

który generuje

def foo(a, b), do: {:ok, a, b} 

jeśli zadzwonisz, że będzie produkować

foo(1, 2) 
# {:ok, 1, 2} 

Można również zdefiniować makro jak to bez unquote_splicing i po prostu przejść w dół połączoną nazwę i argumenty def:

defmacro warp(name_and_args, do: code) do 
    quote do 
    def unquote(name_and_args) do 
     unquote(code) 
    end 
    end 
end 

Oznacza to, czego potrzeba, aby wywołaj warp tak, jakby wywołać def, na przykład:

warp foo(a, b), do: {:ok, a, b} 
1

Oto bardzo prosty przykład:

defmodule SomeMacro do 
    defmacro warp(name, status) do 
    quote do 
     def unquote(name)(args) do 
     {unquote(status), Enum.join(args, " - ")} 
     end 
    end 
    end 
end 

defmodule SomeModule do 
    require SomeMacro 
    SomeMacro.warp :something, :ok 
end 

A jeśli uruchomisz go w IEX w ten sposób:

iex(1)> SomeModule.something([1,2,3]) 
{:ok, "1 - 2 - 3"} 

iex(2)> SomeModule.something(["one", "two", "three"]) 
{:ok, "one - two - three"}