Hey,
I’m trying to understand how distinguish between code that run on compile time and how do you follow that code execution.
For example, how can I know which part of Phoenix view is executing at compile time.
The rule of thumb is, that code inside of a def
/defp
is run during runtime, while code outside of it, is run during compile time.
An exception to this rule are macros, that is one of the reasons why they are annotated accordingly in the documentation. Regardless where they are, they are expanded during compile time, and therefore anything outside of a quote
in the macro is therefore also run during compile time.
Templates in phoenix gets compiled into elixir functions during compiletime, though nothing in the template should be evaluated during compiletime, except for macros, as already mentioned.
There is also this blogpost: https://medium.com/@fxn/how-does-elixir-compile-execute-code-c1b36c9ec8cf
Can’t tell much about its quality, didn’t read it, but it seems to be from the same author who explained the parallel compiler very well in another blog post.
Thank you!
That make sense.
While @NobbZ answer is more or less correct there are few exceptions:
- Macros are functions that returns AST (do not need to use
quote
) and can execute any code. In other words these are definition of “here be dragons” - Not all code in
def
/defp
blocks will be executed in runtime
For example with default configuration c:init/1
in Plug.Builder
will be executed in compile time, so this will print Hello there!
in the compile time:
defmodule FooPlug do
def init(opts) do
IO.puts("Hello there!")
opts
end
def call(conn, _opts) do
IO.puts("General Kenobi")
conn
end
end
defmodule Pipeline do
use Plug.Builder
plug FooPlug
end
As you can always call “regular” functions in macros as well:
defmodule Foo do
defmacro print_in_compiletime(msg) do
IO.puts(msg)
nil
end
end
defmodule Bar do
import Foo
def foo do
print_in_compiletime "Hello there!"
end
end
Additionally you can force execution of some code during compile time by using unquote
within function body:
defmodule Foo do
def foo do
IO.puts(unquote(IO.inspect("What the hell")))
end
end
Things aren’t that simple… so I might have a library that I use and it will call my callbacks/functions at compile time and I have no idea. Except if I look at the source code or documentation.
Can I cause a bug if I don’t aware that a function is executing at compile time?