Могу ли я расширить макрос внутри цитаты другого макроса в Elixir? - PullRequest
0 голосов
/ 14 февраля 2020

Учитывая приведенный ниже код, строка use Composite, user_opts: user_opts заканчивается как [{:user_opts, [line: 3, counter: {MockUserNode1, 2}], Automaton.Node}] внутри с использованием (опции) в качестве опции. Есть ли способ вставить этот код во внешний макрос?

defmacro __using__(user_opts) do
    a =
      if Enum.member?(Composite.types(), user_opts[:node_type]) do
        IO.inspect(user_opts)

        quote bind_quoted: [user_opts: user_opts] do
          use DynamicSupervisor
          use Composite, user_opts: user_opts
        end
      else
        quote do: use(Action)
      end
end

1 Ответ

1 голос
/ 14 февраля 2020

Отвечая на поставленный вопрос: вполне возможно вызывать макросы из других макросов, просто в конце рекурсивно вводить AST.

defmodule DeeplyUsed do
  defmacro __using__(opts) do
    quote bind_quoted: [opts: opts] do
      opts
    end
  end
end

defmodule Used do
  defmacro __using__(opts) do
    quote bind_quoted: [opts: opts] do
      use DeeplyUsed, opts: opts
    end
  end
end

defmodule Using do
  use Used, line: 3, counter: {MockUserNode1, 2}
end

Тем не менее, ваша проблема вызвана.


Sidenote: [{:user_opts, _, Automaton.Node}] выглядит действительно очень подозрительно, это не то, как списки ключевых слов цитируются. Начните с явного удаления из кавычек и регистрации того, что там происходит user_opts.

defmacro __using__(user_opts) do
  IO.inspect(user_opts, label: "Outside")
  quote do
    IO.inspect(unquote(user_opts), label: "Inside")
    use Composite, user_opts: unquote(user_opts)
  end
end
...