Skip to content

Commit 16ce33a

Browse files
committed
Changed some grammar and punctuation in Getting Started Guide
Minor changes to some of the grammar and punctuation in the Getting Started Guide. Hopefully nothing too opinionated, a comma here, a word change there. Intended to make the guide clearer, and improve readability.
1 parent 83da4c1 commit 16ce33a

13 files changed

+30
-30
lines changed

Diff for: getting-started/alias-require-and-import.markdown

+1-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ end
166166

167167
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.
168168

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:
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:
170170

171171
```elixir
172172
defmodule Foo.Bar do

Diff for: getting-started/binaries-strings-and-char-lists.markdown

+1-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ iex> rest
153153
"llo"
154154
```
155155

156-
This finishes our tour of bitstrings, binaries and strings. A string is a UTF-8 encoded binary, and a binary is a bitstring where the number of bits is divisible by 8. Although this shows the flexibility Elixir provides to work with bits and bytes, 99% of the time you will be working with binaries and using the `is_binary/1` and `byte_size/1` functions.
156+
This finishes our tour of bitstrings, binaries and strings. A string is a UTF-8 encoded binary, and a binary is a bitstring where the number of bits is divisible by 8. Although this shows the flexibility Elixir provides for working with bits and bytes, 99% of the time you will be working with binaries and using the `is_binary/1` and `byte_size/1` functions.
157157

158158
## Char lists
159159

Diff for: getting-started/comprehensions.markdown

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ iex> for <<r::8, g::8, b::8 <- pixels>>, do: {r, g, b}
122122
[{213, 45, 132}, {64, 76, 32}, {76, 0, 0}, {234, 32, 15}]
123123
```
124124

125-
A bitstring generator can be mixed with the "regular" enumerable generators and provides filters as well.
125+
A bitstring generator can be mixed with "regular" enumerable generators, and supports filters as well.
126126

127127
## Results other than lists
128128

Diff for: getting-started/enumerables-and-streams.markdown

+4-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ iex> Enum.reduce(1..3, 0, &+/2)
3030
6
3131
```
3232

33-
Since the Enum module was designed to work across different data types, its API is limited to functions that are useful across many data types. For specific operations, you may need to reach to modules specific to the data types. For example, if you want to insert an element at a given position in a list, you should use the `List.insert_at/3` function from [the `List` module](/docs/stable/elixir/List.html), as it would make little sense to insert a value into, for example, a range.
33+
Since the Enum module was designed to work across different data types, its API is limited to functions that are useful across many data types. For specific operations, you may need to reach for modules specific to the data type. For example, if you want to insert an element at a given position in a list, you should use the `List.insert_at/3` function from [the `List` module](/docs/stable/elixir/List.html), as it would make little sense to insert a value into, for example, a range.
3434

3535
We say the functions in the `Enum` module are polymorphic because they can work with diverse data types. In particular, the functions in the `Enum` module can work with any data type that implements [the `Enumerable` protocol](/docs/stable/elixir/Enumerable.html). We are going to discuss Protocols in a later chapter, for now we are going to move on to a specific kind of enumerable called streams.
3636

@@ -91,7 +91,7 @@ iex> 1..100_000 |> Stream.map(&(&1 * 3)) |> Stream.filter(odd?)
9191
#Stream<[enum: 1..100000, funs: [...]]>
9292
```
9393

94-
Many functions in the `Stream` module accept any enumerable as argument and return a stream as result. It also provides functions for creating streams, possibly infinite. For example, `Stream.cycle/1` can be used to create a stream that cycles a given enumerable infinitely. Be careful to not call a function like `Enum.map/2` on such streams, as they would cycle forever:
94+
Many functions in the `Stream` module accept any enumerable as an argument and return a stream as a result. It also provides functions for creating streams, possibly infinite. For example, `Stream.cycle/1` can be used to create a stream that cycles a given enumerable infinitely. Be careful to not call a function like `Enum.map/2` on such streams, as they would cycle forever:
9595

9696
```iex
9797
iex> stream = Stream.cycle([1, 2, 3])
@@ -109,7 +109,7 @@ iex> Enum.take(stream, 3)
109109
["h", "e", "ł"]
110110
```
111111

112-
Another interesting function is `Stream.resource/3` which can be used to wrap around resources, guaranteeing they are opened right before enumeration and closed afterwards, even in case of failures. For example, we can use it to stream a file:
112+
Another interesting function is `Stream.resource/3` which can be used to wrap around resources, guaranteeing they are opened right before enumeration and closed afterwards, even in the case of failures. For example, we can use it to stream a file:
113113

114114
```iex
115115
iex> stream = File.stream!("path/to/file")
@@ -119,6 +119,6 @@ iex> Enum.take(stream, 10)
119119

120120
The example above will fetch the first 10 lines of the file you have selected. This means streams can be very useful for handling large files or even slow resources like network resources.
121121

122-
The amount of functions and functionality in [`Enum`](/docs/stable/elixir/Enum.html) and [`Stream`](/docs/stable/elixir/Stream.html) modules can be daunting at first but you will get familiar with them case by case. In particular, focus on the `Enum` module first and only move to `Stream` for the particular scenarios where laziness is required to either deal with slow resources or large, possibly infinite, collections.
122+
The amount of functions and functionality in the [`Enum`](/docs/stable/elixir/Enum.html) and [`Stream`](/docs/stable/elixir/Stream.html) modules can be daunting at first, but you will get familiar with them case by case. In particular, focus on the `Enum` module first and only move to `Stream` for the particular scenarios where laziness is required, to either deal with slow resources or large, possibly infinite, collections.
123123

124124
Next we'll look at a feature central to Elixir, Processes, which allows us to write concurrent, parallel and distributed programs in an easy and understandable way.

Diff for: getting-started/introduction.markdown

+2-2
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ When going through this getting started guide, it is common to have questions, a
7474
* [elixir-talk mailing list](https://groups.google.com/group/elixir-lang-talk)
7575
* [elixir tag on StackOverflow](https://stackoverflow.com/questions/tagged/elixir)
7676

77-
When doing so, remember those two tips:
77+
When doing so, remember these two tips:
7878

7979
* Instead of asking "how to do X in Elixir", ask "how to solve Y in Elixir". In other words, don't ask how to implement a particular solution, instead describe the problem at hand. Stating the problem gives more context and less bias for a correct answer.
8080

81-
* In case things are not working as expected, please include as much information in your report, for example: your Elixir version, the code snippet and the error message along side the error stacktrace. Use sites like [Gist](https://gist.github.com/) to paste this information.
81+
* In case things are not working as expected, please include as much information as you can in your report, for example: your Elixir version, the code snippet and the error message alongside the error stacktrace. Use sites like [Gist](https://gist.github.com/) to paste this information.

Diff for: getting-started/io-and-the-file-system.markdown

+2-2
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,8 @@ hello world
163163

164164
However, this requires some attention. A list may represent either a bunch of bytes or a bunch of characters and which one to use depends on the encoding of the IO device. If the file is opened without encoding, the file is expected to be in raw mode, and the functions in the `IO` module starting with `bin*` must be used. Those functions expect an `iodata` as argument; i.e., they expect a list of integers representing bytes and binaries to be given.
165165

166-
On the other hand, `:stdio` and files opened with `:utf8` encoding work with the remaining functions in the `IO` module. Those functions expect a `char_data` as argument, that is, a list of characters or strings.
166+
On the other hand, `:stdio` and files opened with `:utf8` encoding work with the remaining functions in the `IO` module. Those functions expect a `char_data` as an argument, that is, a list of characters or strings.
167167

168-
Although this is a subtle difference, you only need to worry about those details if you intend to pass lists to those functions. Binaries are already represented by the underlying bytes and as such their representation is always raw.
168+
Although this is a subtle difference, you only need to worry about these details if you intend to pass lists to those functions. Binaries are already represented by the underlying bytes and as such their representation is always raw.
169169

170170
This finishes our tour of IO devices and IO related functionality. We have learned about four Elixir modules - [`IO`](/docs/stable/elixir/IO.html), [`File`](/docs/stable/elixir/File.html), [`Path`](/docs/stable/elixir/Path.html) and [`StringIO`](/docs/stable/elixir/StringIO.html) - as well as how the <abbr title="Virtual Machine">VM</abbr> uses processes for the underlying IO mechanisms and how to use `chardata` and `iodata` for IO operations.

Diff for: getting-started/maps-and-dicts.markdown

+4-4
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ query = from w in Weather,
6060
select: w
6161
```
6262

63-
Those features are what prompted keyword lists to be the default mechanism for passing options to functions in Elixir. In chapter 5, when we discussed the `if/2` macro, we mentioned the following syntax is supported:
63+
These features are what prompted keyword lists to be the default mechanism for passing options to functions in Elixir. In chapter 5, when we discussed the `if/2` macro, we mentioned the following syntax is supported:
6464

6565
```iex
6666
iex> if false, do: :this, else: :that
@@ -76,7 +76,7 @@ iex> if(false, [do: :this, else: :that])
7676

7777
In general, when the keyword list is the last argument of a function, the square brackets are optional.
7878

79-
In order to manipulate keyword lists, Elixir provides [the `Keyword` module](/docs/stable/elixir/Keyword.html). Remember though keyword lists are simply lists, and as such they provide the same linear performance characteristics as lists. The longer the list, the longer it will take to find a key, to count the number of items, and so on. For this reason, keyword lists are used in Elixir mainly as options. If you need to store many items or guarantee one-key associates with at maximum one-value, you should use maps instead.
79+
In order to manipulate keyword lists, Elixir provides [the `Keyword` module](/docs/stable/elixir/Keyword.html). Remember, though, keyword lists are simply lists, and as such they provide the same linear performance characteristics as lists. The longer the list, the longer it will take to find a key, to count the number of items, and so on. For this reason, keyword lists are used in Elixir mainly as options. If you need to store many items or guarantee one-key associates with at maximum one-value, you should use maps instead.
8080

8181
Although we can pattern match on keyword lists, it is rarely done in practice since pattern matching on lists require the number of items and their order to match:
8282

@@ -215,6 +215,6 @@ The `Dict` module allows any developer to implement their own variation of `Dict
215215

216216
That said, you may be wondering, which of `Keyword`, `Map` or `Dict` modules should you use in your code? The answer is: it depends.
217217

218-
If your code is expecting one specific data structure as argument, use the respective module as it leads to more assertive code. For example, if you expect a keyword as an argument, explicitly use the `Keyword` module instead of `Dict`. However, if your API is meant to work with any dictionary, use the `Dict` module (and make sure to write tests that pass different dict implementations as arguments).
218+
If your code is expecting one specific data structure as an argument, use the respective module as it leads to more assertive code. For example, if you expect a keyword as an argument, explicitly use the `Keyword` module instead of `Dict`. However, if your API is meant to work with any dictionary, use the `Dict` module (and make sure to write tests that pass different dictionary implementations as arguments).
219219

220-
This concludes our introduction to associative data structures in Elixir. You will find out that given keyword lists and maps, you will always have the right tool to tackle problems that require associative data structures in Elixir.
220+
This concludes our introduction to associative data structures in Elixir. You will find out that, given keyword lists and maps, you will always have the right tool to tackle problems that require associative data structures in Elixir.

Diff for: getting-started/module-attributes.markdown

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ Plug.Adapters.Cowboy.http MyPlug, []
150150

151151
In the example above, we have used the `plug/1` macro to connect functions that will be invoked when there is a web request. Internally, every time you call `plug/1`, the Plug library stores the given argument in a `@plugs` attribute. Just before the module is compiled, Plug runs a callback that defines a function (`call/2`) which handles http requests. This function will run all plugs inside `@plugs` in order.
152152

153-
In order to understand the underlying code, we'd need macros, so we will revisit this pattern in the meta-programming guide. However the focus here is exactly on how using module attributes as storage allow developers to create DSLs.
153+
In order to understand the underlying code, we'd need macros, so we will revisit this pattern in the meta-programming guide. However the focus here is on how using module attributes as storage allows developers to create DSLs.
154154

155155
Another example comes from [the ExUnit framework](/docs/stable/ex_unit/) which uses module attributes as annotation and storage:
156156

Diff for: getting-started/processes.markdown

+3-3
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ Function: #Function<20.90072148/0 in :erl_eval.expr/5>
166166
(stdlib) proc_lib.erl:239: :proc_lib.init_p_do_apply/3
167167
```
168168

169-
Besides providing better error logging, there are a couple other differences: `start/1` and `start_link/1` return `{:ok, pid}` rather than just the PID. This is what enables Tasks to be used in supervision trees. Furthermore, tasks provides convenience functions, like `Task.async/1` and `Task.await/1`, and functionality to ease distribution.
169+
Besides providing better error logging, there are a couple of other differences: `start/1` and `start_link/1` return `{:ok, pid}` rather than just the PID. This is what enables Tasks to be used in supervision trees. Furthermore, Tasks provides convenience functions, like `Task.async/1` and `Task.await/1`, and functionality to ease distribution.
170170

171171
We will explore those functionalities in the ***Mix and OTP guide***, for now it is enough to remember to use Tasks to get better logging.
172172

@@ -194,7 +194,7 @@ defmodule KV do
194194
end
195195
```
196196

197-
Note that the `start_link` function basically spawns a new process that runs the `loop/1` function, starting with an empty map. The `loop/1` function then waits for messages and performs the appropriate action for each message. In case of a `:get` message, it sends a message back to the caller and calls `loop/1` again, to wait for a new message. While the `:put` message actually invokes `loop/1` with a new version of the map, with the given `key` and `value` stored.
197+
Note that the `start_link` function basically spawns a new process that runs the `loop/1` function, starting with an empty map. The `loop/1` function then waits for messages and performs the appropriate action for each message. In the case of a `:get` message, it sends a message back to the caller and calls `loop/1` again, to wait for a new message. While the `:put` message actually invokes `loop/1` with a new version of the map, with the given `key` and `value` stored.
198198

199199
Let's give it a try by running `iex kv.exs`:
200200

@@ -231,7 +231,7 @@ iex> flush
231231
:world
232232
```
233233

234-
Using processes around state and name registering are very common patterns in Elixir applications. However, most of the time, we won't implement those patterns manually as above, but by using one of the many of the abstractions that ships with Elixir. For example, Elixir provides [agents](/docs/stable/elixir/Agent.html) which are simple abstractions around state:
234+
Using processes around state and name registering are very common patterns in Elixir applications. However, most of the time, we won't implement those patterns manually as above, but by using one of the many abstractions that ships with Elixir. For example, Elixir provides [agents](/docs/stable/elixir/Agent.html), which are simple abstractions around state:
235235

236236
```iex
237237
iex> {:ok, pid} = Agent.start_link(fn -> %{} end)

Diff for: getting-started/recursion.markdown

+3-3
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ The first clause has a guard which says "use this definition if and only if `n`
4646

4747
The second definition matches the pattern and has no guard so it will be executed. It first prints our `msg` and then calls itself passing `n - 1` (`2`) as the second argument.
4848

49-
Our `msg` is printed and `print_multiple_times/2` is called again this time with the second argument set to `1`.
49+
Our `msg` is printed and `print_multiple_times/2` is called again, this time with the second argument set to `1`.
5050
Because `n` is now set to `1`, the guard in our first definition of `print_multiple_times/2` evaluates to true, and we execute this particular definition. The `msg` is printed, and there is nothing left to execute.
5151

52-
We defined `print_multiple_times/2` so that no matter what number is passed as the second argument it either triggers our first definition (known as a _base case_) or it triggers our second definition which will ensure that we get exactly one step closer to our base case.
52+
We defined `print_multiple_times/2` so that, no matter what number is passed as the second argument, it either triggers our first definition (known as a _base case_) or it triggers our second definition, which will ensure that we get exactly one step closer to our base case.
5353

5454
## Reduce and map algorithms
5555

@@ -106,7 +106,7 @@ iex math.exs
106106
iex> Math.double_each([1, 2, 3]) #=> [2, 4, 6]
107107
```
108108

109-
Here we have used recursion to traverse a list doubling each element and returning a new list. The process of taking a list and _mapping_ over it is known as a _map algorithm_.
109+
Here we have used recursion to traverse a list, doubling each element and returning a new list. The process of taking a list and _mapping_ over it is known as a _map algorithm_.
110110

111111
Recursion and [tail call](https://en.wikipedia.org/wiki/Tail_call) optimization are an important part of Elixir and are commonly used to create loops. However, when programming in Elixir you will rarely use recursion as above to manipulate lists.
112112

0 commit comments

Comments
 (0)