Hi all, maybe a stupid question here. I find it strange that during the compilation of modules expressions in the modules get executed as well. Example:
defmodule Human do
iex> c "human.exs"
I thought the compilation
c "human.exs" will just compile the source code down to bytecode. I actually expect the bytecode to be executed only when for example some other modules call
Any comments or corrections about this thinking?
My guess: because of macros. You could, for example, read a text file and generate functions based on the contents of that file. If you’d like to execute code when it’s required, you can use the
Compiling Elixir code and executing elixir code are one and the same. I recommend the article by Xavier Noria on the matter: https://medium.com/@fxn/how-does-elixir-compile-execute-code-c1b36c9ec8cf
The article describes how Elixir compile/executes. Yes, it loads the “binary into the Erlang VM using the Erlang code server.” and “Call elixir_compiler_X.FILE/1”.
I would have expect that the
Human module in my example to be loaded into the VM and when
elixir_compiler_X.__FILE__/1 is called nothing would have happened because no source code is invoking it.
Well, you are in fact invoking
IO.puts/2 in your module
Major parts of Elixir are implemented as macros and so is
So what happens when a module file like this is compiled is that everything inside
defmodule/2 (which is also a macro!) is executed.
This means, if you only have
defp/2 statements, you won’t notice them being run because they in turn don’t execute the code blocks passed to them. But if you put other code in the module, that will be executed.
defmodule is a macro. Macros are executed at compile time.
Hmm, that kindda make sense. Since
def is also a macro. If the design of the language was to compile and then not execute the bytecode, then functions will not be evaluated and loaded into memory.
Yes … mostly. Macros are “expanded” rather than compiled. Their return value is AST that the compiler uses in its compilation steps. When macros contain side effects like
IO.puts that is executed when the macro is expanded during an early phase of the overall compile.
Module definition is nested execution, that is not covered in the post.