2015-10-10 16 views
9

tham khảo bài đăng này: How to create a dynamic function name using Elixir macro?.Macro Elixir: cách xác định hàm với tính năng động

Bài đăng ở trên hỏi cách sử dụng macro để tạo hàm không có đối số, nhưng tôi tự hỏi cách tạo hàm bằng một số đối số?

giả sử có một macro warp, tôi chỉ có thể viết mã như:

warp fun, [args], :ok 

và sau đó nó tạo ra mã như:

fun(args), do: :ok 
+0

I ' thật khó để tìm tài liệu về ´unquote_splicing´. Sự thay đổi tiêu đề có thể giúp các googlers tương lai như tôi. – nicooga

Trả lời

9

Nếu bạn muốn tạo ra một danh sách năng động của các đối số, bạn cần phải sử dụng unquote_splicing như thế này:

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

Rồi sau

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

mà tạo ra

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

nếu bạn gọi mà nó sẽ tạo ra

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

Bạn cũng có thể xác định vĩ mô như thế này mà không unquote_splicing và chỉ cần vượt qua xuống tên kết hợp và lập luận để def:

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

Điều này có nghĩa bạn cần gọi số warp như bạn sẽ gọi def, ví dụ:

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

Dưới đây là một ví dụ rất đơn giản:

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 

Và nếu bạn chạy nó trong IEX như thế này:

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

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

Các vấn đề liên quan