Reputation: 469
refer this post: How to create a dynamic function name using Elixir macro?.
The post above asked how to use macro to generate function without arguments, but I wonder how to generate functions with some arguments ?
assume there is a macro warp
, I could just write code like:
warp fun, [args], :ok
and then it generate code like:
fun(args), do: :ok
Upvotes: 13
Views: 2775
Reputation: 54674
If you want to generate a dynamic list of arguments, you need to use unquote_splicing
, like this:
defmacro warp(name, argument_names, code) do
quote do
def unquote(name)(unquote_splicing(argument_names)) do
unquote(code)
end
end
end
Then later:
warp :foo, [a, b], {:ok, a, b}
which generates:
def foo(a, b), do: {:ok, a, b}
if you call that it will produce:
foo(1, 2)
# {:ok, 1, 2}
You can also define the macro like this without unquote_splicing
and just pass down the combined name and arguments to def
:
defmacro warp(name_and_args, do: code) do
quote do
def unquote(name_and_args) do
unquote(code)
end
end
end
This means you need to invoke warp
like you would invoke def
, for example:
warp foo(a, b), do: {:ok, a, b}
Upvotes: 18
Reputation: 7385
Here's a very simple example:
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
And if you run it in IEX like this:
iex(1)> SomeModule.something([1,2,3])
{:ok, "1 - 2 - 3"}
iex(2)> SomeModule.something(["one", "two", "three"])
{:ok, "one - two - three"}
👍
Upvotes: 1