diff --git a/getting_started/1.markdown b/getting_started/1.markdown index 4e317f61d..d7d35aad7 100644 --- a/getting_started/1.markdown +++ b/getting_started/1.markdown @@ -10,7 +10,7 @@ Welcome! In this tutorial we are going to show you how to get started with Elixir. This chapter will cover installation and how to get started with the Interactive Elixir shell called IEx. -If you find any errors in the tutorial or in the website, [please report a bug or send a pull request to our issues tracker](https://github.com/elixir-lang/elixir-lang.github.com). If you suspect it is a language bug, [please let us know in the language issues tracker](https://github.com/elixir-lang/elixir/issues). +If you find any errors in the tutorial or on the website, [please report a bug or send a pull request to our issue tracker](https://github.com/elixir-lang/elixir-lang.github.com). If you suspect it is a language bug, [please let us know in the language issue tracker](https://github.com/elixir-lang/elixir/issues). Let's get started! @@ -71,11 +71,13 @@ If the tests pass, you are ready to go. Otherwise, feel free to open an issue [i When you install Elixir, you will have three new executables: `iex`, `elixir` and `elixirc`. If you compiled Elixir from source or are using a packaged version, you can find these inside the `bin` directory. -For now, let's start by running `iex` which stands for Interactive Elixir. In interactive mode, we can type any Elixir expression and get its result straight away. Let's warm up with some basic arithmetic expressions: +For now, let's start by running `iex` which stands for Interactive Elixir. In interactive mode, we can type any Elixir expression and get its result straight away. Let's warm up with some basic expressions: ```text Interactive Elixir - press Ctrl+C to exit (type h() ENTER for help) +iex> 40 + 2 +42 iex> "hello" <> " world" "hello world" ``` diff --git a/getting_started/10.markdown b/getting_started/10.markdown index 8b13fbb8c..80594b224 100644 --- a/getting_started/10.markdown +++ b/getting_started/10.markdown @@ -30,7 +30,7 @@ end Math.sum_list([1,2,3], 0) #=> 6 ``` -In the example above, we invoke `sum_list` giving a list `[1,2,3]` and the initial value `0` as arguments. When a function has many clauses, we will try each clause until we find one that matches according to the pattern matching rules. In this case, the list `[1,2,3]` matches against `[h|t]` which assigns `h = 1` and `t = [2,3]` while `acc` is set to 0. +In the example above, we invoke `sum_list` giving a list `[1,2,3]` and the initial value `0` as arguments. When a function has many clauses, we will try each clause until we find one that matches according to the pattern matching rules. In this case, the list `[1,2,3]` matches against `[h|t]` which assigns `h = 1` and `t = [2,3]` while `acc` is set to `0`. Then, we add the head of the list to the accumulator `h + acc` and call `sum_list` again, recursively, passing the tail of the list as argument. The tail will once again match `[h|t]` until the list is empty, as seen below: diff --git a/getting_started/11.markdown b/getting_started/11.markdown index 449b78880..5cd2d8710 100644 --- a/getting_started/11.markdown +++ b/getting_started/11.markdown @@ -127,9 +127,9 @@ Note that importing a module automatically requires it. ## 11.4 Aliases -At this point, you may be wondering, what exactly is an Elixir alias? How is it represented? +At this point, you may be wondering, what exactly an Elixir alias is an how it is represented? -An alias in Elixir is a capitalized identifier (like `String`, `Keyword`, etc) which is converted to an atom representing a module during compilation. For instance, the `String` alias translates by default to the atom `Elixir.String`: +An alias in Elixir is a capitalized identifier (like `String`, `Keyword`, etc) which is converted to an atom representing a module during compilation. For instance, the `String` alias translates by default to the atom `:"Elixir.String"`: ```iex iex> is_atom(String) diff --git a/getting_started/13.markdown b/getting_started/13.markdown index 95d9e1124..78d828566 100644 --- a/getting_started/13.markdown +++ b/getting_started/13.markdown @@ -17,7 +17,7 @@ iex> Enum.map(%{1 => 2, 3 => 4}, fn {k, v} -> k * v end) [2, 12] ``` -The Enum module provides a huge range of functions to transform, sort, group, filter and retrieve items from enumerables. It is one of the modules developers use frequently in their Elixir code. +The `Enum` module provides a huge range of functions to transform, sort, group, filter and retrieve items from enumerables. It is one of the modules developers use frequently in their Elixir code. Elixir also provides ranges: @@ -28,7 +28,7 @@ iex> Enum.reduce(1..3, 0, &+/2) 6 ``` -Since the Enum module was designed to work accross different data types, its API is limitted to functions that are useful accross 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/List.html), as it would make little sense to insert a value into a range. +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/List.html), as it would make little sense to insert a value into , for example, a range. 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/Enumerable.html). We are going to discuss Protocols in a later chapter, now we are going to move on to a specific kind of enumerable called streams. @@ -59,13 +59,13 @@ iex> 1..100_000 |> Stream.map(&(&1 * 3)) |> Stream.filter(&Integer.odd?/1) |> En 7500000000 ``` -Instead of generating intermediate lists, streams create a series of computations that are invoked only when we pass it to the `Enum` module. Streams are useful when working with large, *possibly infite*, collections. +Instead of generating intermediate lists, streams create a series of computations that are invoked only when we pass it to the `Enum` module. Streams are useful when working with large, *possibly infinite*, collections. ## 13.3 Streams Streams are lazy, composable enumerables. -They are lazy because, as shown in the example above, `1..100_000 |> Stream.map(&(&1 * 3))` returns a data type, an actual stream, that represents the `map` computation: +They are lazy because, as shown in the example above, `1..100_000 |> Stream.map(&(&1 * 3))` returns a data type, an actual stream, that represents the `map` computation over the range `1..100_000`: ```iex iex> 1..100_000 |> Stream.map(&(&1 * 3)) @@ -79,7 +79,7 @@ iex> 1..100_000 |> Stream.map(&(&1 * 3)) |> Stream.filter(&Integer.odd?/1) #Stream<1..100_000, chain: [...]> ``` -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 infite. For example, `Stream.cycle/1` can be used to create a stream that cycles around a given enumerable. Be careful to not call a function like `Enum.map/2` on such streams, as they would cycle forever: +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 around a given enumerable. Be careful to not call a function like `Enum.map/2` on such streams, as they would cycle forever: ```iex iex> stream = Stream.cycle([1, 2, 3]) @@ -107,4 +107,4 @@ iex> Enum.take(stream, 10) 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. -The amount of functions and functionality in [`Enum`](/docs/stable/Enum.html) and [`Stream`](/docs/stable/Stream.html) modules can be daunting at first, but you will get familiar with them case by case when needed. In particular, focus on the Enum module first and only move to Streams for the particular scenarios where laziness is required to either deal with slow resources or infinite collections. +The amount of functions and functionality in [`Enum`](/docs/stable/Enum.html) and [`Stream`](/docs/stable/Stream.html) modules can be daunting at first, but you will get familiar with them case by case when needed. 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 infinite collections. diff --git a/getting_started/14.markdown b/getting_started/14.markdown index d29155faf..1563bea5f 100644 --- a/getting_started/14.markdown +++ b/getting_started/14.markdown @@ -37,7 +37,7 @@ iex> Process.alive?(self()) true ``` -Process get much more interesting when we are able to send and receive messages. +Processes get much more interesting when we are able to send and receive messages. ## 14.2 send and receive diff --git a/getting_started/15.markdown b/getting_started/15.markdown index 9cfe5392d..e8c910674 100644 --- a/getting_started/15.markdown +++ b/getting_started/15.markdown @@ -12,7 +12,7 @@ We have originally sketched this chapter to come much earlier in the getting sta ## 15.1 The IO module -The IO module in Elixir is the main mechanism for reading and writing to the standard io (`:stdio`), standard error (`:stderr`), files and other IO devices. Usage of the module is pretty straight-forward: +The `IO` module in Elixir is the main mechanism for reading and writing to the standard io (`:stdio`), standard error (`:stderr`), files and other IO devices. Usage of the module is pretty straight-forward: ```iex iex> IO.puts "hello world" @@ -53,7 +53,7 @@ iex> {:ok, file} = File.open "another", [:write, :utf8] {:ok, #PID<0.48.0>} ``` -Besides functions for opening, reading and writing files, the `File` module has many functions that work on the filesystem. Those functions are named after their UNIX equivalents. For exmaple, `File.rm/1` can be used to remove files, `File.mkdir/1` to create directories, `File.mkdir_p/1` creates directories guaranteeing their parents exists and there is even `File.cp_r/2` and `File.rm_rf/2` which copy and remove files and directories recursively. +Besides functions for opening, reading and writing files, the `File` module has many functions that work on the filesystem. Those functions are named after their UNIX equivalents. For example, `File.rm/1` can be used to remove files, `File.mkdir/1` to create directories, `File.mkdir_p/1` creates directories guaranteeing their parents exists and there is even `File.cp_r/2` and `File.rm_rf/2` which copy and remove files and directories recursively. You will also notice that functions in the File module have two variants, one with `!` (bang) in its name and others without. For example, when we read the "hello" file above, we have used the one without `!`. Let's try some new examples: @@ -164,7 +164,7 @@ hello world :ok ``` -However, this requires some attention. A char list needs to be encoded into bytes when written to disk and that depends when 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. it expects a list of bytes and binaries to be given. If you provide a list of codepoints and those codepoints have value more than 255, the operation will fail since we won't know how to encode them. +However, this requires some attention. A char list needs to be encoded into bytes when written to disk and that 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. it expects a list of bytes and binaries to be given. If you provide a list of codepoints and those codepoints have value more than 255, the operation will fail since we won't know how to encode them. On the other hand, `:stdio` and files opened with `:utf8` encoding work with the remaining functions in the `IO` module and those expect a `char_data` as argument, i.e. they expect a list of characters or strings to be given. diff --git a/getting_started/17.markdown b/getting_started/17.markdown index ae66f7e63..f0360fcaf 100644 --- a/getting_started/17.markdown +++ b/getting_started/17.markdown @@ -35,7 +35,7 @@ end # Just empty map is blank defimpl Blank, for: Map do - # Keep ind mind we could not pattern match on %{} because + # Keep in mind we could not pattern match on %{} because # it matches on all maps. We can however check if the size # is zero (and size is a fast operation). def blank?(map), do: map_size(map) == 0 @@ -83,7 +83,7 @@ iex> Blank.blank?("hello") ## 17.1 Protocols and structs -The power of Elixir's extensibility comes when protocols and structs are mixed. +The power of Elixir's extensibility comes when protocols and structs are used together. In the previous chapter, we have learned that, although structs are maps, they do not share protocol implementations with maps. Let's define a `User` struct as in the previous chapter: diff --git a/getting_started/2.markdown b/getting_started/2.markdown index 244309d30..1f676f0b4 100644 --- a/getting_started/2.markdown +++ b/getting_started/2.markdown @@ -31,7 +31,7 @@ iex> 10 / 2 5.0 ``` -Notice `10 / 2` returned a float `5.0` instead of an integer. This is expected. In Elixir the operator `/` always returns a float. If you want to do integer division or get the division remainder, you can invoke the `div` and `rem` functions: +Notice that `10 / 2` returned a float `5.0` instead of an integer. This is expected. In Elixir, the operator `/` always returns a float. If you want to do integer division or get the division remainder, you can invoke the `div` and `rem` functions: ```iex iex> div(10, 2) @@ -44,7 +44,7 @@ iex> rem 10, 3 Notice that parentheses are not required in order to invoke a function. -Elixir also supports shorcut notations for entering binaries, octals and hexadecimal numbers: +Elixir also supports shortcut notations for entering binary, octal and hexadecimal numbers: ```iex iex> 0x1F @@ -64,7 +64,7 @@ iex> 1.0e-10 1.0e-10 ``` -Floats in Elixir are double precision, accurate up to 16 digits. +Floats in Elixir are 64 bit double precision. ## 2.2 Booleans @@ -86,7 +86,7 @@ iex> is_boolean(1) false ``` -Throughout this tutorial and in Elixir documentation, you will see functions mentioned in the format `is_boolean/1`. The first part is the function name and the number is its arity, i.e. the number of arguments the function expects. +Throughout this tutorial and in Elixir documentation, you will see functions mentioned in the format `is_boolean/1`. The first part is the function name and the number is the arity, i.e. the number of arguments the function expects. You can also use `is_integer/1`, `is_float/1` or `is_number/1` to check if an argument is an integer, float or any of them. @@ -147,7 +147,7 @@ world Notice the `IO.puts/1` function returns the atom `:ok` as result after printing. -Strings in Elixir are represented internally by binaries (i.e. a sequence of bytes): +Strings in Elixir are represented internally by binaries which are sequences of bytes: ```iex iex> is_binary("hellö") @@ -212,7 +212,7 @@ iex> add_two.(2) 4 ``` -Keep in mind that a variable defined inside the function does not affect its surroundings: +Keep in mind that a variable assigned to inside a function does not affect its surrounding environment: ```iex iex> x = 42 @@ -243,7 +243,7 @@ iex> [1, true, 2, false, 3, true] -- [true, false] [1, 2, 3, true] ``` -Throughout the tutorial, we will talk a lot about head and tail of a list. A head is the first element of a list and tail is the remaining of a list. They can be retrieved with the functions `hd/1` and `tl/1`. Let's assign a list to a variable and retrieve its head and tail: +Throughout the tutorial, we will talk a lot about the head and tail of a list. The head is the first element of a list and the tail is the remainder of a list. They can be retrieved with the functions `hd/1` and `tl/1`. Let's assign a list to a variable and retrieve its head and tail: ```iex iex> list = [1,2,3] @@ -262,7 +262,7 @@ iex> hd [] Oops! -We will revisit lists a couple times in the following chapters. If you want to look ahead, the "Pattern matching", "Binaries, strings and char lists" and "Enumerables and streams" chapters are particularly interesting. +We will revisit lists a couple of times in the following chapters. If you want to look ahead, the "Pattern matching", "Binaries, strings and char lists" and "Enumerables and streams" chapters are particularly interesting. ## 2.7 Tuples @@ -292,9 +292,9 @@ Notice that `set_elem/3` returned a new tuple. The original tuple stored in the ## 2.8 Lists or tuples? -You are probably wondering: what is the difference in between a list and a tuple? +You are probably wondering what the difference is between lists and tuples? -That's an excellent question. Tuples are useful when you have a fixed number of fields or when you usually access those items by position. Lists, on the other hand, are useful when the items need to be enumerated. +Tuples are useful when you have a fixed number of fields or when you usually access those items by position. Lists, on the other hand, are useful when the items need to be enumerated. One very common use case for tuples is to use them to return extra information from a function. For example, we can use the `File.read/1` function to read a file: @@ -307,9 +307,9 @@ iex> File.read("path/to/unknown/file") If the path given to `File.read/1` exists, it returns a tuple with the atom `:ok` as first element and the contents as second. Otherwise, it returns `:error` and the error reason. -The difference in between tuples and lists is important because it reflects on the operations you will perform on them. Tuples are fast when you need to get its size or access one element in a particular position. On the other hand, those operations are linear on lists: if you need to access the nth-item of a list, Elixir needs to go item by item until we retrieve the desired one. +The difference between tuples and lists is important because it reflects on the operations you will perform on them. Tuples are fast when you need to get its size or access one element in a particular position. On the other hand, those operations are linear on lists: if you need to access the nth-item of a list, Elixir needs to go item by item until we retrieve the desired one. -This is the reason there is a `elem/2` function to access a tuple item but there is no builtin equivalent for lists: +This is the reason there is a `elem/2` function to access a tuple item but there is no built-in equivalent for lists: ```iex iex> tuple = {:ok, "hello"} @@ -324,4 +324,4 @@ Finally, notice we have used 4 counting functions so far: `byte_size/1` (for the `length` is used when the number of elements needs to be calculated. For example, calling `length` will iterate the whole list to find the number of elements in that list. `size` is the opposite, it means the value is pre-calculated and stored somewhere, therefore retrieving it is a cheap operation. That said, we use `byte_size` to get the number of bytes in a string, which is cheap, but retrieving the number of unicode characters uses `String.length`, since the whole string needs to be iterated. -Elixir also provides `Port`, `Reference`s and `PID`s as data types (usually used in process communication), and we will take a quick look at them when talking about processes. For now, let's take a look at some of the basic operator to use with our basic types. +Elixir also provides `Port`, `Reference` and `PID` as data types (usually used in process communication), and we will take a quick look at them when talking about processes. For now, let's take a look at some of the basic operators to use with our basic types. diff --git a/getting_started/3.markdown b/getting_started/3.markdown index 403f2c341..252edb291 100644 --- a/getting_started/3.markdown +++ b/getting_started/3.markdown @@ -17,7 +17,7 @@ iex> [1,2,3] -- [2] [1,3] ``` -String concatenation is done via `<>`: +String concatenation is done with `<>`: ```iex iex> "foo" <> "bar" @@ -111,4 +111,4 @@ The reason we can compare different data types is pragmatism. Sorting algorithms You don't actually need to memorize this ordering, but it is important just to know an order exists. -Well, that is it for the introduction. In the next chapter, we are going to discuss some basic functions, data types conversions and a bit of control-flow. +Well, that is it for the introduction. In the next chapter, we are going to discuss some basic functions, data type conversions and a bit of control-flow. diff --git a/getting_started/4.markdown b/getting_started/4.markdown index fc5dad00f..f340a8f81 100644 --- a/getting_started/4.markdown +++ b/getting_started/4.markdown @@ -28,7 +28,7 @@ iex> 2 = x ** (MatchError) no match of right hand side value: 1 ``` -Notice we `1 = x` is a valid expression and it matched because both the left and right side are equal to 1. When the sides do not match, a `MatchError` is reported. +Notice that `1 = x` is a valid expression and it matched because both the left and right side are equal to 1. When the sides do not match, a `MatchError` is raised. Also, in Elixir parlance, we don't say a variable is assigned. We say a variable is bound or not. A variable can only be bound while on the left side: @@ -87,7 +87,7 @@ iex> a 1 ``` -Lists also supporting matching on its head and tail: +Lists also support matching on its head and tail: ```iex iex> [head | tail] = [1, 2, 3] diff --git a/getting_started/5.markdown b/getting_started/5.markdown index 260fc7661..ac8463c86 100644 --- a/getting_started/5.markdown +++ b/getting_started/5.markdown @@ -6,7 +6,7 @@ guide: 5 # {{ page.title }} -In this chapter, we will learn about `case`, `cond` and `if` control-flow structures +In this chapter, we will learn about `case`, `cond` and `if` control-flow structures. ## 5.1 case @@ -90,7 +90,7 @@ The first clause above will only match when `x` is positive. The Erlang VM only * `trunc(number)` * `tuple_size(tuple)` -Keep in mind errors in guards do not leak but simply the guard fail: +Keep in mind errors in guards do not leak but simply let the guard fail: ```iex iex> hd(1) @@ -130,7 +130,7 @@ The number of arguments in each anonymous function clause needs to be the same, ### 5.2 cond -`case` is useful when you need to match against different values. However, in many circunstances, we want to check different conditions and find the first one that evaluates to true. In such cases, one may use `cond`: +`case` is useful when you need to match against different values. However, in many circumstances, we want to check different conditions and find the first one that evaluates to true. In such cases, one may use `cond`: ```iex iex> cond do @@ -197,7 +197,7 @@ iex> if nil do "This will" ``` -One curiosity about `if/2` and `unless/2` is that they are implemented as macros in the language, they are not keywords (as they would be in many languages). You can check the documentation and the source of `if/2` in [the `Kernel` module docs](/docs/stable/Kernel.html). The `Kernel` module is also where operators like `+/2` and functions like `is_function/2` are defined, all automatically imported and available in your code by default. +An interesting thing about `if/2` and `unless/2` is that they are implemented as macros in the language, they are not keywords (as they would be in many languages). You can check the documentation and the source of `if/2` in [the `Kernel` module docs](/docs/stable/Kernel.html). The `Kernel` module is also where operators like `+/2` and functions like `is_function/2` are defined, all automatically imported and available in your code by default. ### 5.4 `do` blocks @@ -262,4 +262,4 @@ iex> case 1, do: (x -> "Got #{x}") "Got 1" ``` -Although it is rare to use the keyword syntax with `case` and `cond`, we will see keyword lists play an important role in the language and are quite common in my functions and macros. We will explore them a bit more in a future chapter, but before, it is time to talk about "Binaries, strings and char lists". \ No newline at end of file +Although it is rare to use the keyword syntax with `case` and `cond`, we will see keyword lists play an important role in the language and are quite common in my functions and macros. We will explore them a bit more in a future chapter, but before, it is time to talk about "Binaries, strings and char lists". diff --git a/getting_started/6.markdown b/getting_started/6.markdown index 84ce6fa59..32184ef43 100644 --- a/getting_started/6.markdown +++ b/getting_started/6.markdown @@ -6,7 +6,7 @@ guide: 6 # {{ page.title }} -In "Basic Types", we have learned about strings and used the `is_binary/1` function for checks: +In "Basic Types", we learned about strings and used the `is_binary/1` function for checks: ```iex iex> string = "hello" @@ -15,7 +15,7 @@ iex> is_binary string true ``` -In this chapter, we will understand what are binaries, how they associate with strings and what a single-quoted value, `'like this'`, means in Elixir. +In this chapter, we will understand what binaries are, how they associate with strings and what a single-quoted value, `'like this'`, means in Elixir. ## 6.1 UTF-8 and Unicode @@ -54,9 +54,9 @@ iex> String.codepoints("hełło") You will see that Elixir has excellent support for working with strings and it also supports many of the Unicode operations. In fact, Elixir passes all the tests showcased in the ["The string type is broken"](http://mortoray.com/2013/11/27/the-string-type-is-broken/) article. -However, strings are just part of the story. If a string is a binary and we have used a `is_binary/1` function, Elixir probably has an underlying type, empowering strings, and that is exactly true. Let's talk about binaries! +However, strings are just part of the story. If a string is a binary and we have used a `is_binary/1` function, Elixir probably has an underlying type empowering strings, and that is exactly true. Let's talk about binaries! -## 6.2 Binaries (and bit strings) +## 6.2 Binaries (and bitstrings) In Elixir, you can define a binary using `<<>>`: @@ -99,7 +99,7 @@ iex> <<256 :: size(16)>> # use 16 bits to store the number (2 bytes) <<1, 0>> iex> <<256 :: utf8>> # the number is a codepoint "Ā" -iex> <<256 :: utf8, 0>> # the number is a codepoint +iex> <<256 :: utf8, 0>> <<196, 128, 0>> ``` @@ -118,7 +118,7 @@ iex> bit_size(<< 1 :: size(1)>>) 1 ``` -Interesting... the value is no longer a binary, but a bit string! I.e. it is just a bunch of bits. So a binary is a bitstring when the number of bits is divisible by 8! +Interesting... the value is no longer a binary, but a bitstring! I.e. it is just a bunch of bits. So a binary is a bitstring when the number of bits is divisible by 8! We can also pattern match on binaries / bitstrings: @@ -149,7 +149,7 @@ iex> rest "llo" ``` -This finishes our tour on bit strings, binaries and strings. A string is a UTF-8 encoded binary and a binary is a bitstring where the number of bits is divisble 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. +This finishes our tour on 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. ## 6.3 Char lists @@ -163,7 +163,7 @@ iex> is_list 'hełło' You can see that, instead of containing bytes, a char list contains the codepoints of the characters in between single-quotes. So while a double-quotes represents a string (i.e. a binary), single-quotes represents a char list (i.e. a list). -In practice, char lists are used mostly when interfacing with Erlang, in particular older libraries that do not accept binaries as arguments. You can convert in between char list to a string or a string to a char list by using the `to_string/1` and `to_char_list/1` functions: +In practice, char lists are used mostly when interfacing with Erlang, in particular older libraries that do not accept binaries as arguments. You can convert a char list to a string and back by using the `to_string/1` and `to_char_list/1` functions: ```iex iex> to_char_list "hełło" diff --git a/getting_started/7.markdown b/getting_started/7.markdown index 4c30adcb4..be6e02055 100644 --- a/getting_started/7.markdown +++ b/getting_started/7.markdown @@ -150,19 +150,19 @@ iex> %{map | :c => 3} ** (ArgumentError) argument error ``` -Both access and update syntaxes above require the given keys to exist. For example, the last line failed because there is no `:c` in the map. This is very useful when you are working with maps on a tight loop and you expect only certain keys to exist. +Both access and update syntaxes above require the given keys to exist. For example, the last line failed because there is no `:c` in the map. This is very useful when you are working with maps where you only expect certain keys to exist. In future chapters, we will also learn about structs, which provide compile-time guarantees and the foundation for polymorphism in Elixir. Structs are built on top of maps where the update guarantees above are proven to be quite useful. -Manipulating maps is done via [the `Map` module](/docs/stable/Map.html) module and that it provides a very similar API to the `Keyword` module. This is because both modules implement the `Dict` behaviour. +Manipulating maps is done via [the `Map` module](/docs/stable/Map.html), it provides a very similar API to the `Keyword` module. This is because both modules implement the `Dict` behaviour. -> Maps were recently introduced into the Erlang VM with [the `EEP 43`](www.erlang.org/eeps/eep-0043.html). Erlang 17 provides a partial implementation of the EEP, where only "small maps" are supported. This means maps have good performance characteristics only when storing at maximum a couple dozens keys. To fill in this gap, Elixir also provides [the `HashDict` module](/docs/stable/HashDict.html) which uses a hashing algorithm to provide a dictionary that supports hundreds of thousands keys with good performance. +> Maps were recently introduced into the Erlang VM with [EEP 43](www.erlang.org/eeps/eep-0043.html). Erlang 17 provides a partial implementation of the EEP, where only "small maps" are supported. This means maps have good performance characteristics only when storing at maximum a couple of dozens keys. To fill in this gap, Elixir also provides [the `HashDict` module](/docs/stable/HashDict.html) which uses a hashing algorithm to provide a dictionary that supports hundreds of thousands keys with good performance. ## 7.3 Dicts In Elixir, both keyword lists and maps are called dictionaries. In other words, a dictionary is like an interface (we call them behaviours in Elixir) and both keyword lists and maps implement this interface. -This interface is defined in the [the `Dict` module](/docs/stable/Dict.html) module which also provides an API that delegates to the underyling implementations: +This interface is defined in the [the `Dict` module](/docs/stable/Dict.html) module which also provides an API that delegates to the underlying implementations: ```iex iex> keyword = [] @@ -175,10 +175,10 @@ iex> Dict.put(map, :a, 1) %{a: 1} ``` -The Dict module allows any developer to implement their own variation of Dict, with specific characteristics, and hook into existing Elixir code. The Dict module also provides functions that are meant to work accross dictionaries. For example, `Dict.equal?/2` can compare two dictionaries of any kind. +The `Dict` module allows any developer to implement their own variation of `Dict`, with specific characteristics, and hook into existing Elixir code. The `Dict` module also provides functions that are meant to work across dictionaries. For example, `Dict.equal?/2` can compare two dictionaries of any kind. -That said, you may be wondering, which of `Keyword`, `Map` or `Dict` modules should you use in your code? The answer is: it depends. +That said, you may be wondering, which of `Keyword`, `Map` or `Dict` modules you should use in your code? The answer is: it depends. -If your code is expecting a keyword as argument, use explicitly the `Keyword` module. If a map, the `Map` module. However, if your API is meant to work with any dictionary, use the `Dict` module (and be sure to write tests that pass different dict implementations as arguments). +If your code is expecting a keyword as argument, explicitly use the `Keyword` module. If a map, the `Map` module. 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). -This concludes our introduction to associative data structures in Elixir. You will find out that in between keyword lists and maps, you will have the right tools to tackle many problems that require associative data structures in Elixir. +This concludes our introduction to associative data structures in Elixir. You will find out that between keyword lists and maps, you will have the right tools to tackle many problems that require associative data structures in Elixir. diff --git a/getting_started/8.markdown b/getting_started/8.markdown index 21879cbec..bf4c95997 100644 --- a/getting_started/8.markdown +++ b/getting_started/8.markdown @@ -57,11 +57,11 @@ Elixir projects are usually organized into three directories: * lib - contains elixir code (usually `.ex` files) * test - contains tests (usually `.exs` files) -When working on actual projects, our build tool called `mix` will be responsible to compile and set up the proper paths for you. For learning purposes, Elixir supports scripted modes, which is more flexible and does not generate any artifact. +When working on actual projects, our build tool called `mix` will be responsible to compile and set up the proper paths for you. For learning purposes, Elixir supports scripted modes, which is more flexible and does not generate any compiled artifacts. ## 8.2 Scripted mode -In addition to the Elixir file `.ex`, Elixir also supports `.exs` files for scripting. Elixir treats both files exactly the same way, the only difference is in intention. `.ex` files are meant to be compiled while `.exs` files are used for scripting, without the need for compilation. For instance, one can create a file called `math.exs`: +In addition to the Elixir file extension `.ex`, Elixir also supports `.exs` files for scripting. Elixir treats both files exactly the same way, the only difference is in intention. `.ex` files are meant to be compiled while `.exs` files are used for scripting, without the need for compilation. For instance, one can create a file called `math.exs`: ```elixir defmodule Math do