Elixir 宏 - 作为变量传递的参数的模式匹配

Elixir macros - pattern match on an argument passed as a variable

我试图更好地理解 Elixir 宏,但我无法弄清楚如何设置一个场景,在该场景中我可以模式匹配我传递给宏的参数,当我的值是m 试图通过是一个变量。这里有一个简单的例子来说明:

macro_test.ex

defmodule MacroTest do
  use MacroTest.UseMe

  def run() do
    atom = :hello_world

    macro_a(atom)
  end
end

use_me.ex

defmodule MacroTest.UseMe do
  defmacro __using__(_) do
    quote do

      defmacro macro_a(:hello_world) do
        quote do
          "Success!"
        end
      end

      defmacro macro_a(:some_other_atom) do
        quote do
          "Did something else..."
        end
      end

    end
  end
end

当我尝试编译这段代码时,出现错误

== Compilation error in file lib/macro_test.ex ==
** (FunctionClauseError) no function clause matching in MacroTest.macro_a/1  

如果我改变最初的run()函数,让原子直接传递给宏,比如macro_a(:hello_world),那么它compiles/runs就好了。

我如何改变这种情况,以便宏可以对作为变量提供的值进行模式匹配,而不是文字值本身?

这取决于你想做什么。在编译时宏 运行,并对部分源代码进行操作(与上述源代码返回的 运行 时间值相反)。所以在这种情况下,宏知道它已被一个名为 atom 的变量调用,但它无法知道该变量已在调用函数的前面分配给

您可以在 运行 时间检查给定变量的值:

  defmacro macro_a(a) do
    quote do
      case unquote(a) do
        :hello_world ->
          "Success!"
        :some_other_atom ->
          "Did something else..."
      end
    end
  end

也就是说,每次调用 macro_a 都会被上面的 case 表达式替换,使用传递的任何变量或其他表达式作为参数。