Макросы эликсира - сопоставление с образцом аргумента, переданного как переменная - PullRequest
0 голосов
/ 04 октября 2019

Я пытаюсь лучше понять макросы Elixir, но мне трудно понять, как настроить сценарий, в котором я могу сопоставить шаблон с аргументом, который я передаю макросу, когда значение, которое я пытаюсьпередать это переменная. Вот простой пример для иллюстрации:

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), то он компилируется / работает очень хорошо.

Как можноЯ изменяю этот сценарий так, чтобы макрос мог сопоставлять шаблон по значению, которое было предоставлено как переменная, а не само литеральное значение?

1 Ответ

2 голосов
/ 04 октября 2019

Это зависит от того, что вы хотите сделать. Макросы выполняются во время компиляции и работают с частями исходного кода (в отличие от значения времени выполнения, возвращаемого указанным фрагментом исходного кода). Таким образом, в этом случае макрос знает, что он был вызван с переменной 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, используя любую переменную или другое выражение, переданное в качестве аргумента.

...