Skip to content

Commit 4c5db05

Browse files
committed
Very small polishes in chapter 13
- Fixed some minor grammar errors - Rephrased a couple of sentences - Added a note at the very end of the chapter (about module nesting)
1 parent 394f3db commit 4c5db05

File tree

1 file changed

+33
-18
lines changed

1 file changed

+33
-18
lines changed

getting_started/13.markdown

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ defmodule Math do
2020
end
2121
```
2222

23-
From now on, any reference to `List` will automatically expand to `Math.List`. In case one wants to access the original `List`, it can be done by accessing the module via `Elixir`:
23+
From now on, any reference to `List` will automatically expand to `Math.List`. In case one wants to access the original `List`, it can be done by prefixing the module name with `Elixir.`:
2424

2525
```elixir
2626
List.flatten #=> uses Math.List.flatten
@@ -74,13 +74,13 @@ iex> Integer.is_odd(3)
7474
true
7575
```
7676

77-
In Elixir, `Integer.is_odd/1` is defined as a macro so it can be used as guards. This means that, in order to invoke `Integer.is_odd/1`, we need to first require the `Integer` module.
77+
In Elixir, `Integer.is_odd/1` is defined as a macro so that it can be used as a guard. This means that, in order to invoke `Integer.is_odd/1`, we need to first require the `Integer` module.
7878

7979
In general a module does not need to be required before usage, except if we want to use the macros available in that module. An attempt to call a macro that was not loaded will raise an error. Note that like the `alias` directive, `require` is also lexically scoped. We will talk more about macros in a later chapter.
8080

8181
## 13.3 import
8282

83-
We use `import` whenever we want to easily access functions or macros from other modules without using the qualified name. For instance, if we want to use the `duplicate` function from `List` several times, we can simply import it:
83+
We use `import` whenever we want to easily access functions or macros from other modules without using the fully-qualified name. For instance, if we want to use the `duplicate/2` function from the `List` module several times, we can simply import it:
8484

8585
```iex
8686
iex> import List, only: [duplicate: 2]
@@ -89,7 +89,7 @@ iex> duplicate :ok, 3
8989
[:ok, :ok, :ok]
9090
```
9191

92-
In this case, we are importing only the function `duplicate` (with arity 2) from `List`. Although `:only` is optional, its usage is recommended. `:except` could also be given as an option.
92+
In this case, we are importing only the function `duplicate` (with arity 2) from `List`. Although `:only` is optional, its usage is recommended in order to avoid importing all the functions of a given module inside the namespace. `:except` could also be given as an option in order to import everything in a module *except* a list of functions.
9393

9494
`import` also supports `:macros` and `:functions` to be given to `:only`. For example, to import all macros, one could write:
9595

@@ -103,24 +103,24 @@ Or to import all functions, you could write:
103103
import Integer, only: :functions
104104
```
105105

106-
Note that `import` is also **lexically scoped**, this means we can import specific macros inside specific functions:
106+
Note that `import` is **lexically scoped** too. This means that we can import specific macros or functions inside function definitions:
107107

108108
```elixir
109109
defmodule Math do
110110
def some_function do
111111
import List, only: [duplicate: 2]
112-
# call duplicate
112+
duplicate(:ok, 10)
113113
end
114114
end
115115
```
116116

117117
In the example above, the imported `List.duplicate/2` is only visible within that specific function. `duplicate/2` won't be available in any other function in that module (or any other module for that matter).
118118

119-
Note that importing a module automatically requires it.
119+
Note that `import`ing a module automatically `require`s it.
120120

121121
## 13.4 Aliases
122122

123-
At this point, you may be wondering, what exactly an Elixir alias is and how it is represented?
123+
At this point you may be wondering: what exactly an Elixir alias is and how is it represented?
124124

125125
An alias in Elixir is a capitalized identifier (like `String`, `Keyword`, etc) which is converted to an atom during compilation. For instance, the `String` alias translates by default to the atom `:"Elixir.String"`:
126126

@@ -129,16 +129,16 @@ iex> is_atom(String)
129129
true
130130
iex> to_string(String)
131131
"Elixir.String"
132-
iex> :"Elixir.String"
133-
String
132+
iex> :"Elixir.String" == String
133+
true
134134
```
135135

136136
By using the `alias/2` directive, we are simply changing what an alias translates to.
137137

138-
Aliases work as described because in the Erlang VM (and consequently Elixir), modules are represented by atoms. For example, that's the mechanism we use to call Erlang modules:
138+
Aliases work as described because in the Erlang VM (and consequently Elixir) modules are represented by atoms. For example, that's the mechanism we use to call Erlang modules:
139139

140140
```iex
141-
iex> :lists.flatten([1,[2],3])
141+
iex> :lists.flatten([1, [2], 3])
142142
[1, 2, 3]
143143
```
144144

@@ -147,11 +147,11 @@ This is also the mechanism that allows us to dynamically call a given function i
147147
```iex
148148
iex> mod = :lists
149149
:lists
150-
iex> mod.flatten([1,[2],3])
151-
[1,2,3]
150+
iex> mod.flatten([1, [2], 3])
151+
[1, 2, 3]
152152
```
153153

154-
In other words, we are simply calling the function `flatten` on the atom `:lists`.
154+
We are simply calling the function `flatten` on the atom `:lists`.
155155

156156
## 13.5 Nesting
157157

@@ -164,9 +164,20 @@ defmodule Foo do
164164
end
165165
```
166166

167-
The example above will define two modules `Foo` and `Foo.Bar`. The second can be accessed as `Bar` inside `Foo` as long as they are in the same lexical scope. If later the developer decides to move `Bar` to another file, it will need to be referenced by its full name (`Foo.Bar`) or an alias needs to be set using the `alias` directive discussed above.
167+
The example above will define two modules: `Foo` and `Foo.Bar`. The second can be accessed as `Bar` inside `Foo` as long as they are in the same lexical scope.
168+
169+
If later the `Bar` module is moved outside the `Foo` module definition, it will need to be referenced by its full name (`Foo.Bar`) or an alias will need to be set using the `alias` directive discussed above. The `Bar` module definition will change too. This code is equivalent to the example above:
170+
171+
```elixir
172+
defmodule Foo.Bar do
173+
end
174+
175+
defmodule Foo do
176+
alias Foo.Bar, as: Bar
177+
end
178+
```
168179

169-
In other words, the code above is exactly the same as:
180+
The code above is exactly the same as:
170181

171182
```elixir
172183
defmodule Elixir.Foo do
@@ -176,4 +187,8 @@ defmodule Elixir.Foo do
176187
end
177188
```
178189

179-
As we will see in later chapters, aliases also play a crucial role in macros, to guarantee they are hygienic. With this we are almost finishing our tour about Elixir modules, the last topic to cover is module attributes.
190+
**Note**: in Elixir, you don't have to define the `Foo` module before being able to define the `Foo.Bar` module, as the language translates all module names to atoms anyway. You can define arbitrarily-nested modules without defining any module in the chain (e.g., `Foo.Bar.Baz` without defining `Foo` or `Foo.Bar` first).
191+
192+
As we will see in later chapters, aliases also play a crucial role in macros, to guarantee they are hygienic.
193+
194+
With this we are almost finishing our tour about Elixir modules. The last topic to cover is module attributes.

0 commit comments

Comments
 (0)