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
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.
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
defpblocks will be executed in runtime
For example with default configuration
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?