Если вы посмотрите на файл 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 . Таким образом, в основном все смешанные проекты помещаются в стек, и их можно проверить, есть ли дубликаты в именах.