venomnert
Module Attribute behaviour during compilation
I am just doing some poking around with module attribute and I created the following code:
defmodule ModuleAttribute do
Module.register_attribute(__MODULE__, :test_attribute, accumulate: true)
@test_attribute 1
@test_attribute 10
def increase(), do: IO.inspect(@test_attribute, label: "Value")
@test_attribute 20
end
When I run iex -S mix i get the following values
iex(40)> ModuleAttribute.increase
Value: [10, 1]
If my understanding of elixir compilation is correct, should it be [1, 10, 20]? I am not sure why 20 didn’t get added in during compilation.
Most Liked Responses
OvermindDL1
For note, module attributes are a lot like normal bindings, just saving you from typing the unquote part.
So this:
defmodule ModuleAttribute do
@thing 1
@thing 2
def blah(), do: @thing # returns 2
@thing 3
end
Is the same as this:
defmodule ModuleAttribute do
thing = 1
thing = 2
def blah(), do: unquote(thing) # returns 2
thing = 3
end
And thus this with an accumulated attribute:
defmodule ModuleAttribute do
Module.register_attribute(__MODULE__, :thing, accumulate: true)
@thing 1
@thing 2
def blah(), do: @thing # returns [2, 1]
@thing 3
end
Is the same as this:
defmodule ModuleAttribute do
thing = []
thing = [1 | thing]
thing = [2 | thing] # So this is now [2, 1]
def blah(), do: unquote(thing) # returns [2, 1]
thing = [3 | thing]
end
LostKobrakai
This is correct. Module attributes always have the value assigned to it in lines above the call. Basically you “hardcode” the parameter of IO.inspect at the time line 5 is compiled.
NobbZ
20 isn’t in the list, because you only add it to the list after reading it. Each usage of a module attribute will only ever know about values that have been assigned before its usage, pretty much like regular variables.








