Macros Elixir宏:如何用动态算术定义函数

Macros Elixir宏:如何用动态算术定义函数,macros,elixir,Macros,Elixir,请参阅此帖子: 上面的帖子问如何使用宏生成没有参数的函数,但我想知道如何生成带有一些参数的函数 假设有一个宏warp,我可以编写如下代码: warp fun, [args], :ok fun(args), do: :ok 然后生成如下代码: warp fun, [args], :ok fun(args), do: :ok 下面是一个非常简单的示例: defmodule SomeMacro do defmacro warp(name, status) do quote do

请参阅此帖子:

上面的帖子问如何使用宏生成没有参数的函数,但我想知道如何生成带有一些参数的函数

假设有一个宏
warp
,我可以编写如下代码:

warp fun, [args], :ok
fun(args), do: :ok
然后生成如下代码:

warp fun, [args], :ok
fun(args), do: :ok

下面是一个非常简单的示例:

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
如果在IEX中像这样运行它:

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

iex(2)> SomeModule.something(["one", "two", "three"])
{:ok, "one - two - three"}
defmacro warp(name, argument_names, code) do
  quote do
    def unquote(name)(unquote_splicing(argument_names)) do
      unquote(code)
    end
  end
end

如果要生成参数的动态列表,需要使用以下命令:

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

iex(2)> SomeModule.something(["one", "two", "three"])
{:ok, "one - two - three"}
defmacro warp(name, argument_names, code) do
  quote do
    def unquote(name)(unquote_splicing(argument_names)) do
      unquote(code)
    end
  end
end
随后:

warp :foo, [a, b], {:ok, a, b}
由此产生:

def foo(a, b), do: {:ok, a, b}
如果您称之为,它将产生:

foo(1, 2)
# {:ok, 1, 2}
您也可以这样定义宏,而无需
unquote\u拼接
,只需将组合名称和参数传递给
def

defmacro warp(name_and_args, do: code) do
  quote do
    def unquote(name_and_args) do
      unquote(code)
    end
  end
end
这意味着您需要像调用
def
一样调用
warp
,例如:

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

我很难找到关于“unquote\u拼接”的文档。标题的改变可能会对像我这样的未来谷歌人有所帮助。这是一个非常酷、非常好的回答。但是,如果我们真的想像调用def(您的最后一行)一样调用它,而不是在一行代码中
,DO:*1-line-only*
表单(aka:
warp-foo(a,b)DO…end
)无需担心。我很肯定它会“起作用”。如果我理解正确,Elixir将接受
,do:…
do。。。结束
版本完全相同。对于这个令人敬畏的答案@Bukov yep,这只是语法,sugar和Elixir很乐意接受这两种变体。谢谢你的客气话