I tried creating a mix project it did not have the config.exs
so I created the file.
I referred config.exs
from a phoenix project.
I see the config.exs
does not have module definition. I tried declaring a standalone function in a .ex
file it raised an error as expected
** (ArgumentError) cannot invoke def/2 outside module
Then I presumed that .exs
can be written without defmodule
then I saw the mix.exs
it has module definition. Why it is so?
My question why it is preffred to keep config.exs
without module definition but mix.exs
with the definition?
When we should use defmodule in .exs
and when not?
If you take a look at mix.exs
file you can notice the:
use Mix.Project
Now this file contains:
@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
is a macro defined in elixir/kernel.ex even if it is in a strange form and it is invoked by __using__
from mix.exs
. Since you cannot invoke macros outside of modules you need to have a module in your mix.exs
file.
To illustrate this more clearly, let's try to delete the module in mix.exs
and run the project:
* (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)
So the answer to your question is that the hook @after_compile
cannot be called without a module since hooks by themselves are macros. The hook most probably is used to load the project automatically after all the files were compiled.
PS: push/3
function calls an interesting module function:
Mix.ProjectStack.push(atom, config, file)
If you look at the source of ProjectStack module you can observe that it is a state machine based on Agent. So basically all mix projects are pushed into the stack and they can be checked whether there are duplicates in names.