diff --git a/lib/elixir/pages/getting-started/basic-types.md b/lib/elixir/pages/getting-started/basic-types.md index d1b15331a83..43ebb304eac 100644 --- a/lib/elixir/pages/getting-started/basic-types.md +++ b/lib/elixir/pages/getting-started/basic-types.md @@ -26,7 +26,7 @@ iex> 10 / 2 5.0 ``` -Notice that `10 / 2` returned a float `5.0` instead of an integer `5`. 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 `5`. This is expected. In Elixir, the operator [`/`](`//2`) always returns a float. If you want to do integer division or get the division remainder, you can invoke the [`div`](`div/2`) and [`rem`](`rem/2`) functions: ```elixir iex> div(10, 2) @@ -61,7 +61,7 @@ iex> 1.0e-10 Floats in Elixir are 64-bit precision. -You can invoke the `round` function to get the closest integer to a given float, or the `trunc` function to get the integer part of a float. +You can invoke the [`round`](`round/1`) function to get the closest integer to a given float, or the [`trunc`](`trunc/1`) function to get the integer part of a float. ```elixir iex> round(3.58) @@ -70,7 +70,7 @@ iex> trunc(3.58) 3 ``` -Finally, we work with different data types, we will learn Elixir provides several predicate functions to check for the type of a value. For example, the `is_integer` can be used to check if a value is an integer or not: +Finally, we work with different data types, we will learn Elixir provides several predicate functions to check for the type of a value. For example, [`is_integer`](`is_integer/1`) can be used to check if a value is an integer or not: ```elixir iex> is_integer(1) @@ -79,7 +79,7 @@ iex> is_integer(2.0) false ``` -You can also use `is_float` or `is_number` to check, respectively, if an argument is a float, or either an integer or float. +You can also use [`is_float`](`is_float/1`) or [`is_number`](`is_number/1`) to check, respectively, if an argument is a float, or either an integer or float. ## Identifying functions and documentation @@ -118,7 +118,7 @@ iex> true == false false ``` -Elixir also provides three boolean operators: `or/2`, `and/2`, and `not/1`. These operators are strict in the sense that they expect something that evaluates to a boolean (`true` or `false`) as their first argument: +Elixir also provides three boolean operators: [`or`](`or/2`), [`and`](`and/2`), and [`not`](`not/1`). These operators are strict in the sense that they expect something that evaluates to a boolean (`true` or `false`) as their first argument: ```elixir iex> true and true @@ -219,7 +219,7 @@ iex> "hellö" > Note: if you are running on Windows, there is a chance your terminal does not use UTF-8 by default. You can change the encoding of your current session by running `chcp 65001` before entering IEx. -You can concatenate two strings with the `<>/2` operator: +You can concatenate two strings with the [`<>`](`<>/2`) operator: ```elixir iex> "hello " <> "world!" @@ -252,7 +252,7 @@ iex> "hello\nworld" "hello\nworld" ``` -You can print a string using the `IO.puts/1` function from the `IO` module: +You can print a string using the [`IO.puts`](`IO.puts/1`) function from the `IO` module: ```elixir iex> IO.puts("hello\nworld") @@ -261,7 +261,7 @@ world :ok ``` -Notice that the `IO.puts/1` function returns the atom `:ok` after printing. +Notice that the [`IO.puts`](`IO.puts/1`) function returns the atom `:ok` after printing. Strings in Elixir are represented internally by contiguous sequences of bytes known as binaries: @@ -277,7 +277,7 @@ iex> byte_size("hellö") 6 ``` -Notice that the number of bytes in that string is 6, even though it has 5 graphemes. That's because the grapheme "ö" takes 2 bytes to be represented in UTF-8. We can get the actual length of the string, based on the number of graphemes, by using the `String.length/1` function: +Notice that the number of bytes in that string is 6, even though it has 5 graphemes. That's because the grapheme "ö" takes 2 bytes to be represented in UTF-8. We can get the actual length of the string, based on the number of graphemes, by using the [`String.length`](`String.length/1`) function: ```elixir iex> String.length("hellö") @@ -293,7 +293,7 @@ iex> String.upcase("hellö") ## Structural comparison -Elixir also provides `==`, `!=`, `<=`, `>=`, `<` and `>` as comparison operators. We can compare numbers: +Elixir also provides [`==`](`==/2`), [`!=`](`!=/2`), [`<=`](`<=/2`), [`>=`](`>=/2`), [`<`](``](`>/2`) as comparison operators. We can compare numbers: ```elixir iex> 1 == 1 @@ -322,7 +322,7 @@ iex> 1 == 2.0 false ``` -However, you can use the strict comparison operator `===` and `!==` if you want to distinguish between integers and floats (that's the only difference between these operators): +However, you can use the strict comparison operator [`===`](`===/2`) and [`!==`](`!==/2`) if you want to distinguish between integers and floats (that's the only difference between these operators): ```elixir iex> 1 === 1.0 diff --git a/lib/elixir/pages/getting-started/case-cond-and-if.md b/lib/elixir/pages/getting-started/case-cond-and-if.md index df9b73cdc84..7c2804b935d 100644 --- a/lib/elixir/pages/getting-started/case-cond-and-if.md +++ b/lib/elixir/pages/getting-started/case-cond-and-if.md @@ -1,10 +1,10 @@ # case, cond, and if -In this chapter, we will learn about the `case`, `cond`, and `if` control flow structures. +In this chapter, we will learn about the [`case`](`case/2`), [`cond`](`cond/1`), and [`if`](`if/2`) control flow structures. ## case -`case` allows us to compare a value against many patterns until we find a matching one: +[`case`](`case/2`) allows us to compare a value against many patterns until we find a matching one: ```elixir iex> case {1, 2, 3} do @@ -18,7 +18,7 @@ iex> case {1, 2, 3} do "This clause will match and bind x to 2 in this clause" ``` -If you want to pattern match against an existing variable, you need to use the `^` operator: +If you want to pattern match against an existing variable, you need to use the [`^`](`^/1`) operator: ```elixir iex> x = 1 @@ -69,7 +69,7 @@ The documentation for the `Kernel` module lists all available guards in its side ## if -`case` builds on pattern matching and guards to destructure and match on certain conditions. However, patterns and guards are limited only to certain expressions which are optimized by the compiler. In many situations, you need to write conditions that go beyond what can be expressed with `case`. For those, `if/2` is a useful alternative: +[`case`](`case/2`) builds on pattern matching and guards to destructure and match on certain conditions. However, patterns and guards are limited only to certain expressions which are optimized by the compiler. In many situations, you need to write conditions that go beyond what can be expressed with [`case`](`case/2`). For those, [`if`](`if/2`) is a useful alternative: ```elixir iex> if true do @@ -82,9 +82,9 @@ iex> if false do nil ``` -If the condition given to `if/2` returns `false` or `nil`, the body given between `do`-`end` is not executed and instead it returns `nil`. +If the condition given to [`if`](`if/2`) returns `false` or `nil`, the body given between `do`-`end` is not executed and instead it returns `nil`. -`if/2` also supports `else` blocks: +[`if`](`if/2`) also supports `else` blocks: ```elixir iex> if nil do @@ -95,7 +95,7 @@ iex> if nil do "This will" ``` -This is also a good opportunity to talk about variable scoping in Elixir. If any variable is declared or changed inside `if`, `case`, and similar constructs, the declaration and change will only be visible inside the construct. For example: +This is also a good opportunity to talk about variable scoping in Elixir. If any variable is declared or changed inside [`if`](`if/2`), [`case`](`case/2`), and similar constructs, the declaration and change will only be visible inside the construct. For example: ```elixir iex> x = 1 @@ -108,7 +108,7 @@ iex> x 1 ``` -In said cases, if you want to change a value, you must return the value from the `if`: +In said cases, if you want to change a value, you must return the value from the [`if`](`if/2`): ```elixir iex> x = 1 @@ -123,13 +123,13 @@ iex> x = if true do > #### `if` is a macro {: .info} > -> An interesting note regarding `if/2` is that it is implemented as a macro in the language: it isn't a special language construct as it would be in many languages. You can check the documentation and its source for more information. +> An interesting note regarding [`if`](`if/2`) is that it is implemented as a macro in the language: it isn't a special language construct as it would be in many languages. You can check the documentation and its source for more information. -If you find yourself nesting several `if/2` blocks, you may want to consider using `cond/1` instead. Let's check it out. +If you find yourself nesting several [`if`](`if/2`) blocks, you may want to consider using [`cond`](`cond/1`) instead. Let's check it out. ## cond -If you need to check across several conditions and find the first one that does not evaluate to `nil` or `false`, `cond/1` is a useful construct: +If you need to check across several conditions and find the first one that does not evaluate to `nil` or `false`, [`cond`](`cond/1`) is a useful construct: ```elixir iex> cond do @@ -159,7 +159,7 @@ iex> cond do "This is always true (equivalent to else)" ``` -Similar to `if/2`, `cond` considers any value besides `nil` and `false` to be true: +Similar to [`if`](`if/2`), [`cond`](`cond/1`) considers any value besides `nil` and `false` to be true: ```elixir iex> cond do @@ -171,4 +171,4 @@ iex> cond do ## Summing up -We have concluded the introduction to the most fundamental control-flow constructs in Elixir. Generally speaking, Elixir developers prefer pattern matching and guards, using `case` and function definitions (which we will explore in future chapters), as they are succinct and precise. When your logic cannot be outlined within patterns and guards, you may consider `if/2`, falling back to `cond/1` when there are several conditions to check. +We have concluded the introduction to the most fundamental control-flow constructs in Elixir. Generally speaking, Elixir developers prefer pattern matching and guards, using [`case`](`case/2`) and function definitions (which we will explore in future chapters), as they are succinct and precise. When your logic cannot be outlined within patterns and guards, you may consider [`if`](`if/2`), falling back to [`cond`](`cond/1`) when there are several conditions to check. diff --git a/lib/elixir/pages/getting-started/lists-and-tuples.md b/lib/elixir/pages/getting-started/lists-and-tuples.md index 341361f0a19..b71496c362d 100644 --- a/lib/elixir/pages/getting-started/lists-and-tuples.md +++ b/lib/elixir/pages/getting-started/lists-and-tuples.md @@ -13,7 +13,7 @@ iex> length([1, 2, 3]) 3 ``` -Two lists can be concatenated or subtracted using the `++/2` and `--/2` operators respectively: +Two lists can be concatenated or subtracted using the [`++`](`++/2`) and [`--`](`--/2`) operators respectively: ```elixir iex> [1, 2, 3] ++ [4, 5, 6] @@ -24,7 +24,7 @@ iex> [1, true, 2, false, 3, true] -- [true, false] List operators never modify the existing list. Concatenating to or removing elements from a list returns a new list. We say that Elixir data structures are *immutable*. One advantage of immutability is that it leads to clearer code. You can freely pass the data around with the guarantee no one will mutate it in memory - only transform it. -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 the 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 the list. They can be retrieved with the functions [`hd`](`hd/1`) and [`tl`](`tl/1`). Let's assign a list to a variable and retrieve its head and tail: ```elixir iex> list = [1, 2, 3] @@ -50,7 +50,7 @@ iex> [104, 101, 108, 108, 111] ~c"hello" ``` -When Elixir sees a list of printable ASCII numbers, Elixir will print that as a charlist (literally a list of characters). Charlists are quite common when interfacing with existing Erlang code. Whenever you see a value in IEx and you are not quite sure what it is, you can use the `i/1` to retrieve information about it: +When Elixir sees a list of printable ASCII numbers, Elixir will print that as a charlist (literally a list of characters). Charlists are quite common when interfacing with existing Erlang code. Whenever you see a value in IEx and you are not quite sure what it is, you can use [`i`](`IEx.Helpers.i/1`) to retrieve information about it: ```elixir iex> i ~c"hello" @@ -96,7 +96,7 @@ iex> tuple_size(tuple) 2 ``` -It is also possible to put an element at a particular index in a tuple with `put_elem/3`: +It is also possible to put an element at a particular index in a tuple with [`put_elem`](`put_elem/3`): ```elixir iex> tuple = {:ok, "hello"} @@ -107,7 +107,7 @@ iex> tuple {:ok, "hello"} ``` -Notice that `put_elem/3` returned a new tuple. The original tuple stored in the `tuple` variable was not modified. Like lists, tuples are also immutable. Every operation on a tuple returns a new tuple, it never changes the given one. +Notice that [`put_elem`](`put_elem/3`) returned a new tuple. The original tuple stored in the `tuple` variable was not modified. Like lists, tuples are also immutable. Every operation on a tuple returns a new tuple, it never changes the given one. ## Lists or tuples? @@ -150,9 +150,9 @@ iex> String.split("hello beautiful world") ["hello", "beautiful", "world"] ``` -The `String.split/1` function breaks a string into a list of strings on every whitespace character. Since the amount of elements returned depends on the input, we use a list. +The [`String.split`](`String.split/1`) function breaks a string into a list of strings on every whitespace character. Since the amount of elements returned depends on the input, we use a list. -On the other hand, `String.split_at/2` splits a string in two parts at a given position. Since it always returns two entries, regardless of the input size, it returns tuples: +On the other hand, [`String.split_at`](`String.split_at/2`) splits a string in two parts at a given position. Since it always returns two entries, regardless of the input size, it returns tuples: ```elixir iex> String.split_at("hello world", 3) @@ -161,7 +161,7 @@ iex> String.split_at("hello world", -4) {"hello w", "orld"} ``` -It is also very common to use tuples and atoms to create "tagged tuples", which is a handy return value when an operation may succeed or fail. For example, `File.read/1` reads the contents of a file at a given path, which may or may not exist. It returns tagged tuples: +It is also very common to use tuples and atoms to create "tagged tuples", which is a handy return value when an operation may succeed or fail. For example, [`File.read`](`File.read/1`) reads the contents of a file at a given path, which may or may not exist. It returns tagged tuples: ```elixir iex> File.read("path/to/existing/file") @@ -170,9 +170,9 @@ iex> File.read("path/to/unknown/file") {:error, :enoent} ``` -If the path given to `File.read/1` exists, it returns a tuple with the atom `:ok` as the first element and the file contents as the second. Otherwise, it returns a tuple with `:error` and the error description. As we will soon learn, Elixir allows us to *pattern match* on tagged tuples and effortlessly handle both success and failure cases. +If the path given to [`File.read`](`File.read/1`) exists, it returns a tuple with the atom `:ok` as the first element and the file contents as the second. Otherwise, it returns a tuple with `:error` and the error description. As we will soon learn, Elixir allows us to *pattern match* on tagged tuples and effortlessly handle both success and failure cases. -Given Elixir consistently follows those rules, the choice between lists and tuples get clearer as you learn and use the language. Elixir often guides you to do the right thing. For example, there is an `elem/2` function to access a tuple item: +Given Elixir consistently follows those rules, the choice between lists and tuples get clearer as you learn and use the language. Elixir often guides you to do the right thing. For example, there is an [`elem`](`elem/2`) function to access a tuple item: ```elixir iex> tuple = {:ok, "hello"} @@ -187,6 +187,6 @@ However, given you often don't know the number of elements in a list, there is n When counting the elements in a data structure, Elixir also abides by a simple rule: the function is named `size` if the operation is in constant time (the value is pre-calculated) or `length` if the operation is linear (calculating the length gets slower as the input grows). As a mnemonic, both "length" and "linear" start with "l". -For example, we have used 4 counting functions so far: `byte_size/1` (for the number of bytes in a string), `tuple_size/1` (for tuple size), `length/1` (for list length) and `String.length/1` (for the number of graphemes in a string). We use `byte_size` to get the number of bytes in a string, which is a cheap operation. Retrieving the number of Unicode graphemes, on the other hand, uses `String.length/1`, and may be expensive as it relies on a traversal of the entire string. +For example, we have used 4 counting functions so far: [`byte_size`](`byte_size/1`) (for the number of bytes in a string), [`tuple_size`](`tuple_size/1`) (for tuple size), [`length`](`length/1`) (for list length) and [`String.length`](`String.length/1`) (for the number of graphemes in a string). We use [`byte_size`](`byte_size/1`) to get the number of bytes in a string, which is a cheap operation. Retrieving the number of Unicode graphemes, on the other hand, uses [`String.length`](`String.length/1`), and may be expensive as it relies on a traversal of the entire string. Now that we are familiar with the basic data-types in the language, let's learn important constructs for writing code, before we discuss more complex data structures. diff --git a/lib/elixir/pages/getting-started/pattern-matching.md b/lib/elixir/pages/getting-started/pattern-matching.md index 9836c8514e4..576d5f910e3 100644 --- a/lib/elixir/pages/getting-started/pattern-matching.md +++ b/lib/elixir/pages/getting-started/pattern-matching.md @@ -1,10 +1,10 @@ # Pattern matching -In this chapter, we will learn why the `=` operator in Elixir is called the match operator and how to use it to pattern match inside data structures. We will learn about the pin operator `^` used to access previously bound values. +In this chapter, we will learn why the [`=`](`=/2`) operator in Elixir is called the match operator and how to use it to pattern match inside data structures. We will learn about the pin operator [`^`](`^/1`) used to access previously bound values. ## The match operator -We have used the `=` operator a couple times to assign variables in Elixir: +We have used the [`=`](`=/2`) operator a couple times to assign variables in Elixir: ```elixir iex> x = 1 @@ -13,7 +13,7 @@ iex> x 1 ``` -In Elixir, the `=` operator is actually called *the match operator*. Let's see why: +In Elixir, the [`=`](`=/2`) operator is actually called *the match operator*. Let's see why: ```elixir iex> x = 1 @@ -26,7 +26,7 @@ iex> 2 = x 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. -A variable can only be assigned on the left side of `=`: +A variable can only be assigned on the left side of [`=`](`=/2`): ```elixir iex> 1 = unknown @@ -92,7 +92,7 @@ iex> tail [2, 3] ``` -Similar to the `hd/1` and `tl/1` functions, we can't match an empty list with a head and tail pattern: +Similar to the [`hd`](`hd/1`) and [`tl`](`tl/1`) functions, we can't match an empty list with a head and tail pattern: ```elixir iex> [head | tail] = [] @@ -123,7 +123,7 @@ iex> x = 2 However, there are times when we don't want variables to be rebound. -Use the pin operator `^` when you want to pattern match against a variable's *existing value* rather than rebinding the variable. +Use the pin operator [`^`](`^/1`) when you want to pattern match against a variable's *existing value* rather than rebinding the variable. ```elixir iex> x = 1