Когда мы должны использовать defmodule в файле .exs - PullRequest
2 голосов
/ 04 ноября 2019

Я попытался создать проект микса, у него не было config.exs, поэтому я создал файл.

Я ссылался config.exs из проекта Феникс.

Я вижу config.exs не имеет определения модуля. Я попытался объявить автономную функцию в файле .ex, она вызвала ошибку, как и ожидалось

** (ArgumentError) cannot invoke def/2 outside module

Затем я предположил, что .exs можно написать без defmodule, тогда я увидел mix.exsопределение модуля. Почему так?

Мой вопрос, почему предпочтительнее оставить config.exs без определения модуля, но mix.exs с определением?

Когда мы должны использовать defmodule в .exs, а когда нет?

1 Ответ

2 голосов
/ 05 ноября 2019

Если вы посмотрите на файл mix.exs, вы можете заметить:

use Mix.Project

Теперь этот файл содержит:

  @doc false
  defmacro __using__(_) do
    quote do
      @after_compile Mix.Project
    end
  end

  # Invoked after each Mix.Project is compiled.
  @doc false
  def __after_compile__(env, _binary) do
    push(env.module, env.file)
  end

@after_compileэто макрос, определенный в elixir / kernel.ex , даже если он находится в странной форме и вызывается __using__ из mix.exs. Поскольку вы не можете вызывать макросы вне модулей, вам необходимо иметь модуль в файле mix.exs.

Чтобы проиллюстрировать это более четко, давайте попробуем удалить модуль в mix.exs и запустить проект:

* (ArgumentError) cannot invoke @/1 outside module
    (elixir) lib/kernel.ex:5230: Kernel.assert_module_scope/3
    (elixir) expanding macro: Kernel.@/1
    mix.exs:2: (file)
    (mix) expanding macro: Mix.Project.__using__/1
    mix.exs:2: (file)
    (elixir) expanding macro: Kernel.use/1
    mix.exs:2: (file)

Итак, ответ на ваш вопрос заключается в том, что ловушка @after_compile не может быть вызвана без модуля, поскольку сами ловушки являются макросами. Хук, скорее всего, используется для автоматической загрузки проекта после компиляции всех файлов.

PS: push/3 функция вызывает интересную функцию модуля:

Mix.ProjectStack.push(atom, config, file)

Если вы посмотрите на источник модуля ProjectStack , вы увидите, что это конечный автомат, основанный на Agent . Таким образом, в основном все смешанные проекты помещаются в стек, и их можно проверить, есть ли дубликаты в именах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...