Skip to content

Commit 32d3df9

Browse files
fireproofsocksJosé Valim
authored and
José Valim
committed
Update module-attributes.markdown (elixir-lang#1349)
I wanted to clarify a few things: - module attributes are not constants - Point out ExUnit's use of the `@tag` module attribute a bit earlier. - I wanted to point out the "accumulate" option - I wanted to see an example of calling functions when a module attribute is defined.
1 parent a15d4d2 commit 32d3df9

File tree

1 file changed

+29
-5
lines changed

1 file changed

+29
-5
lines changed

getting-started/module-attributes.markdown

+29-5
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ This section covers built-in attributes. However, attributes can also be used by
7979

8080
## As "constants"
8181

82-
Elixir developers will often use module attributes as constants:
82+
Elixir developers often use module attributes when they wish to make a value more visible or reusable:
8383

8484
```elixir
8585
defmodule MyServer do
@@ -99,7 +99,7 @@ end
9999
warning: undefined module attribute @unknown, please remove access to @unknown or explicitly set it before access
100100
```
101101

102-
Finally, attributes can also be read inside functions:
102+
Attributes can also be read inside functions:
103103

104104
```elixir
105105
defmodule MyServer do
@@ -113,17 +113,41 @@ MyServer.first_data #=> 14
113113
MyServer.second_data #=> 13
114114
```
115115

116-
Every time an attribute is read inside a function, a snapshot of its current value is taken. In other words, the value is read at compilation time and not at runtime. As we are going to see, this also makes attributes useful to be used as storage during module compilation.
116+
This is exactly how [ExUnit](https://hexdocs.pm/ex_unit/ExUnit.Case.html#module-tags) uses the `@tag` attribute to annotate tests (see the "temporary storage" section below for an example).
117117

118-
Any functions may be called when defining a module attribute. However, please note that functions you define in the same module as the attribute itself cannot be called, as they are not yet compiled at the time that the attribute is defined.
118+
Every time an attribute is read inside a function, a snapshot of its current value is taken. In other words, the value is read at compilation time and not at runtime. As we are going to see, this also makes attributes useful as storage during module compilation.
119+
120+
Normally, repeating a module attribute will cause its value to be reassigned, but there are circumstances where you may want to [configure the module attribute](https://hexdocs.pm/elixir/Module.html#register_attribute/3) so that its values are accumulated:
121+
122+
```elixir
123+
defmodule Foo do
124+
Module.register_attribute __MODULE__, :param, accumulate: true
125+
126+
@param :foo
127+
@param :bar
128+
# here @param == [:foo, :bar]
129+
end
130+
```
131+
132+
Functions may be called when defining a module attribute, e.g.
133+
134+
```elixir
135+
defmodule MyApp.Notification do
136+
@service Application.get_env(:my_app, :email_service)
137+
@message Application.get_env(:my_app, :welcome_email)
138+
def welcome(email), do: @service.send_welcome_message(email, @message)
139+
end
140+
```
141+
142+
Be careful, however: *functions defined in the same module as the attribute itself cannot be called* because they have not yet been compiled when the attribute is being defined.
119143

120144
When defining an attribute, do not leave a line break between the attribute name and its value.
121145

122146
## As temporary storage
123147

124148
One of the projects in the Elixir organization is [the `Plug` project](https://github.com/elixir-lang/plug), which is meant to be a common foundation for building web libraries and frameworks in Elixir.
125149

126-
The Plug library also allows developers to define their own plugs which can be run in a web server:
150+
The Plug library allows developers to define their own plugs which can be run in a web server:
127151

128152
```elixir
129153
defmodule MyPlug do

0 commit comments

Comments
 (0)