thojanssens1
Why is __after_compile__/2 called before __before_compile__/1?
defmodule Bar do
@after_compile __MODULE__
defmacro __before_compile__(_env) do
IO.inspect("#{__MODULE__}.__before_compile__")
end
def __after_compile__(_env, _bytecode) do
IO.inspect("#{__MODULE__}.__after_compile__")
end
end
defmodule Foo do
require Bar
@before_compile Bar
@after_compile __MODULE__
def __after_compile__(_env, _bytecode) do
IO.inspect("#{__MODULE__}.__after_compile__")
end
end
Will print:
“Elixir.Bar.after_compile”
“Elixir.Bar.before_compile”
“Elixir.Foo.after_compile”
[Bar, Foo]
Why is after_compile called before before_compile for the Bar module?
Marked As Solved
NobbZ
Baris compiled, you see its output ofBar.__after_compile__Foois going to get compiled, it callsBar.__before_compile__, you see the outputBar.__before_compile__, because__MODULE__isBarin that context. You wan’t to checkenv.modto see the callers module.Foogets actuially compiled, its after compile gets called and you see itsFoo.__after_compile__.
Also Liked
ityonemo
Because you are compiling Foo after Bar.
LostKobrakai
Baz is already compiled when used in MyApp. MyApp is not yet compiled. In macros it’s important to be aware if you‘re working in the context of the macro (__MODULE__ is the module with the macro definition) or if you‘re working on the AST of the macros result, which is effectively becoming part of the module calling the macro (__MODULE__ refers to the module calling the macro).
NobbZ
Again, you need to look into the callers environment. Macros get passed __CALLER__ as a magic variable, so you probably want to Module.register_attribute(__CALLER__.mod, :attr, []) or in this case even more appropriate, as you do not make it accumulating or persistent:
defmacro __using__(_opts) do
quote do
@attr []
end
end
Or instead of the empty list use any other default value you prefer.
Beeing aware of the current context you are in is important for macros.
Perhaps give Metaprogramming Elixir by @chrismccord a read? I only skimmed about the first quarter of it, but it helped me to understand macros enough for my usecase.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








