anchors on listings, figures & tables added

This commit is contained in:
pawel duzinkiewicz 2018-06-09 18:34:35 +02:00
parent 105e252de6
commit 05d3c50279
69 changed files with 2195 additions and 613 deletions

View File

@ -11,6 +11,9 @@ appear in context, a short explanation, and whether that operator is
overloadable. If an operator is overloadable, the relevant trait to use to
overload that operator is listed.
[Table-B-1]: #Table-B-1
<a name="Table-B-1"></a>
<span class="caption">Table B-1: Operators</span>
| Operator | Example | Explanation | Overloadable? |
@ -77,6 +80,9 @@ that is, they dont behave like a function or method call.
Table B-2 shows symbols that appear on their own and are valid in a variety of
locations.
[Table-B-2]: #Table-B-2
<a name="Table-B-2"></a>
<span class="caption">Table B-2: Stand-Alone Syntax</span>
| Symbol | Explanation |
@ -96,6 +102,9 @@ locations.
Table B-3 shows symbols that appear in the context of a path through the module
hierarchy to an item.
[Table-B-3]: #Table-B-3
<a name="Table-B-3"></a>
<span class="caption">Table B-3: Path-Related Syntax</span>
| Symbol | Explanation |
@ -113,6 +122,9 @@ hierarchy to an item.
Table B-4 shows symbols that appear in the context of using generic type
parameters.
[Table-B-4]: #Table-B-4
<a name="Table-B-4"></a>
<span class="caption">Table B-4: Generics</span>
| Symbol | Explanation |
@ -129,6 +141,9 @@ parameters.
Table B-5 shows symbols that appear in the context of constraining generic type
parameters with trait bounds.
[Table-B-5]: #Table-B-5
<a name="Table-B-5"></a>
<span class="caption">Table B-5: Trait Bound Constraints</span>
| Symbol | Explanation |
@ -143,6 +158,9 @@ parameters with trait bounds.
Table B-6 shows symbols that appear in the context of calling or defining
macros and specifying attributes on an item.
[Table-B-6]: #Table-B-6
<a name="Table-B-6"></a>
<span class="caption">Table B-6: Macros and Attributes</span>
| Symbol | Explanation |
@ -155,6 +173,9 @@ macros and specifying attributes on an item.
Table B-7 shows symbols that create comments.
[Table-B-7]: #Table-B-7
<a name="Table-B-7"></a>
<span class="caption">Table B-7: Comments</span>
| Symbol | Explanation |
@ -168,6 +189,9 @@ Table B-7 shows symbols that create comments.
Table B-8 shows symbols that appear in the context of using tuples.
[Table-B-8]: #Table-B-8
<a name="Table-B-8"></a>
<span class="caption">Table B-8: Tuples</span>
| Symbol | Explanation |
@ -184,6 +208,9 @@ Table B-8 shows symbols that appear in the context of using tuples.
Table B-9 shows the contexts in which curly braces are used.
[Table-B-9]: #Table-B-9
<a name="Table-B-9"></a>
<span class="caption">Table B-9: Curly Brackets</span>
| Context | Explanation |
@ -193,6 +220,9 @@ Table B-9 shows the contexts in which curly braces are used.
Table B-10 shows the contexts in which square brackets are used.
[Table-B-10]: #Table-B-10
<a name="Table-B-10"></a>
<span class="caption">Table B-10: Square Brackets</span>
| Context | Explanation |

View File

@ -93,8 +93,10 @@ We could also use the `vec!` macro to make a vector of two integers or a vector
of five string slices. We wouldnt be able to use a function to do the same
because we wouldnt know the number or type of values up front.
Lets look at a slightly simplified definition of the `vec!` macro in Listing
D-1.
Lets look at a slightly simplified definition of the `vec!` macro in Listing D-1.
[Listing-D-1]: #Listing-D-1
<a name="Listing-D-1"></a>
```rust
#[macro_export]
@ -202,6 +204,9 @@ programmer to write code like Listing D-2 using our crate.
<span class="filename">Filename: src/main.rs</span>
[Listing-D-2]: #Listing-D-2
<a name="Listing-D-2"></a>
```rust,ignore
extern crate hello_macro;
#[macro_use]
@ -311,6 +316,9 @@ compile until we add a definition for the `impl_hello_macro` function.
<span class="filename">Filename: hello_macro_derive/src/lib.rs</span>
[Listing-D-3]: #Listing-D-3
<a name="Listing-D-3"></a>
```rust,ignore
extern crate proc_macro;
extern crate syn;

View File

@ -56,10 +56,13 @@ the *.rs* extension. If youre using more than one word in your filename, use
an underscore to separate them. For example, use *hello_world.rs* rather than
*helloworld.rs*.
Now open the *main.rs* file you just created and enter the code in Listing 1-1.
Now open the *main.rs* file you just created and enter the code in [Listing 1-1][Listing-1-1].
<span class="filename">Filename: main.rs</span>
[Listing-1-1]: #Listing-1-1
<a name="Listing-1-1"></a>
```rust
fn main() {
println!("Hello, world!");
@ -200,3 +203,5 @@ Just compiling with `rustc` is fine for simple programs, but as your project
grows, youll want to manage all the options and make it easy to share your
code. Next, well introduce you to the Cargo tool, which will help you write
real-world Rust programs.
[Listing-1-1]: ch01-02-hello-world.html#Listing-1-1

View File

@ -52,10 +52,13 @@ repository along with a *.gitignore* file.
> the `--vcs` flag. Run `cargo new --help` to see the available options.
Open *Cargo.toml* in your text editor of choice. It should look similar to the
code in Listing 1-2.
code in [Listing 1-2][Listing-1-2].
<span class="filename">Filename: Cargo.toml</span>
[Listing-1-2]: #Listing-1-2
<a name="Listing-1-2"></a>
```toml
[package]
name = "hello_cargo"
@ -98,7 +101,7 @@ fn main() {
```
Cargo has generated a Hello, world! program for you, just like the one we wrote
in Listing 1-1! So far, the differences between our previous project and the
in [Listing 1-1][Listing-1-1]! So far, the differences between our previous project and the
project Cargo generates are that Cargo placed the code in the *src* directory,
and we have a *Cargo.toml* configuration file in the top directory.
@ -242,3 +245,6 @@ This is a great time to build a more substantial program to get used to reading
and writing Rust code. So, in Chapter 2, well build a guessing game program.
If you would rather start by learning how common programming concepts work in
Rust, see Chapter 3 and then return to Chapter 2.
[Listing-1-1]: ch01-02-hello-world.html#Listing-1-1
[Listing-1-2]: ch01-03-hello-cargo.html#Listing-1-2

View File

@ -75,11 +75,14 @@ Reopen the *src/main.rs* file. Youll be writing all the code in this file.
The first part of the guessing game program will ask for user input, process
that input, and check that the input is in the expected form. To start, well
allow the player to input a guess. Enter the code in Listing 2-1 into
allow the player to input a guess. Enter the code in [Listing 2-1][Listing-2-1] into
*src/main.rs*.
<span class="filename">Filename: src/main.rs</span>
[Listing-2-1]: #Listing-2-1
<a name="Listing-2-1"></a>
```rust,ignore
use std::io;
@ -392,7 +395,10 @@ version 0.3.14.”
[semver]: http://semver.org
Now, without changing any of the code, lets build the project, as shown in
Listing 2-2.
[Listing 2-2][Listing-2-2].
[Listing-2-2]: #Listing-2-2
<a name="Listing-2-2"></a>
```text
$ cargo build
@ -509,10 +515,13 @@ from a number of packages.
### Generating a Random Number
Now that youve added the `rand` crate to *Cargo.toml*, lets start using
`rand`. The next step is to update *src/main.rs*, as shown in Listing 2-3.
`rand`. The next step is to update *src/main.rs*, as shown in [Listing 2-3][Listing-2-3].
<span class="filename">Filename: src/main.rs</span>
[Listing-2-3]: #Listing-2-3
<a name="Listing-2-3"></a>
```rust,ignore
extern crate rand;
@ -598,11 +607,14 @@ You should get different random numbers, and they should all be numbers between
## Comparing the Guess to the Secret Number
Now that we have user input and a random number, we can compare them. That step
is shown in Listing 2-4. Note that this code wont compile quite yet, as we
is shown in [Listing 2-4][Listing-2-4]. Note that this code wont compile quite yet, as we
will explain.
<span class="filename">Filename: src/main.rs</span>
[Listing-2-4]: #Listing-2-4
<a name="Listing-2-4"></a>
```rust,ignore
extern crate rand;
@ -664,7 +676,7 @@ the code in that arm and moves to the next arm. The next arms pattern,
that arm will execute and print `Too big!` to the screen. The `match`
expression ends because it has no need to look at the last arm in this scenario.
However, the code in Listing 2-4 wont compile yet. Lets try it:
However, the code in [Listing 2-4][Listing-2-4] wont compile yet. Lets try it:
```text
$ cargo build
@ -893,10 +905,13 @@ exiting the program, because the loop is the last part of `main`.
To further refine the games behavior, rather than crashing the program when
the user inputs a non-number, lets make the game ignore a non-number so the
user can continue guessing. We can do that by altering the line where `guess`
is converted from a `String` to a `u32`, as shown in Listing 2-5.
is converted from a `String` to a `u32`, as shown in [Listing 2-5][Listing-2-5].
<span class="filename">Filename: src/main.rs</span>
[Listing-2-5]: #Listing-2-5
<a name="Listing-2-5"></a>
```rust,ignore
// --snip--
@ -965,10 +980,13 @@ You win!
Awesome! With one tiny final tweak, we will finish the guessing game. Recall
that the program is still printing the secret number. That worked well for
testing, but it ruins the game. Lets delete the `println!` that outputs the
secret number. Listing 2-6 shows the final code.
secret number. [Listing 2-6][Listing-2-6] shows the final code.
<span class="filename">Filename: src/main.rs</span>
[Listing-2-6]: #Listing-2-6
<a name="Listing-2-6"></a>
```rust,ignore
extern crate rand;
@ -1022,3 +1040,10 @@ variables, data types, and functions, and shows how to use them in Rust.
Chapter 4 explores ownership, a feature that makes Rust different from other
languages. Chapter 5 discusses structs and method syntax, and Chapter 6
explains how enums work.
[Listing-2-1]: ch02-00-guessing-game-tutorial.html#Listing-2-1
[Listing-2-2]: ch02-00-guessing-game-tutorial.html#Listing-2-2
[Listing-2-3]: ch02-00-guessing-game-tutorial.html#Listing-2-3
[Listing-2-4]: ch02-00-guessing-game-tutorial.html#Listing-2-4
[Listing-2-5]: ch02-00-guessing-game-tutorial.html#Listing-2-5
[Listing-2-6]: ch02-00-guessing-game-tutorial.html#Listing-2-6

View File

@ -43,11 +43,14 @@ these from other programming languages. Lets jump into how they work in Rust.
An *integer* is a number without a fractional component. We used one integer
type in Chapter 2, the `u32` type. This type declaration indicates that the
value its associated with should be an unsigned integer (signed integer types
start with `i`, instead of `u`) that takes up 32 bits of space. Table 3-1 shows
start with `i`, instead of `u`) that takes up 32 bits of space. [Table 3-1][Table-3-1] shows
the built-in integer types in Rust. Each variant in the Signed and Unsigned
columns (for example, `i16`) can be used to declare the type of an integer
value.
[Table-3-1]: #Table-3-1
<a name="Table-3-1"></a>
<span class="caption">Table 3-1: Integer Types in Rust</span>
| Length | Signed | Unsigned |
@ -79,10 +82,13 @@ Additionally, the `isize` and `usize` types depend on the kind of computer your
program is running on: 64 bits if youre on a 64-bit architecture and 32 bits
if youre on a 32-bit architecture.
You can write integer literals in any of the forms shown in Table 3-2. Note
You can write integer literals in any of the forms shown in [Table 3-2][Table-3-2]. Note
that all number literals except the byte literal allow a type suffix, such as
`57u8`, and `_` as a visual separator, such as `1_000`.
[Table-3-2]: #Table-3-2
<a name="Table-3-2"></a>
<span class="caption">Table 3-2: Integer Literals in Rust</span>
| Number literals | Example |
@ -362,3 +368,6 @@ low-level languages, this kind of check is not done, and when you provide an
incorrect index, invalid memory can be accessed. Rust protects you against this
kind of error by immediately exiting instead of allowing the memory access and
continuing. Chapter 9 discusses more of Rusts error handling.
[Table-3-1]: ch03-02-data-types.html#Table-3-1
[Table-3-2]: ch03-02-data-types.html#Table-3-2

View File

@ -148,10 +148,13 @@ instructions that perform some action and do not return a value. *Expressions*
evaluate to a resulting value. Lets look at some examples.
Creating a variable and assigning a value to it with the `let` keyword is a
statement. In Listing 3-1, `let y = 6;` is a statement.
statement. In [Listing 3-1][Listing-3-1], `let y = 6;` is a statement.
<span class="filename">Filename: src/main.rs</span>
[Listing-3-1]: #Listing-3-1
<a name="Listing-3-1"></a>
```rust
fn main() {
let y = 6;
@ -197,7 +200,7 @@ languages, you can write `x = y = 6` and have both `x` and `y` have the value
Expressions evaluate to something and make up most of the rest of the code that
youll write in Rust. Consider a simple math operation, such as `5 + 6`, which
is an expression that evaluates to the value `11`. Expressions can be part of
statements: in Listing 3-1, the `6` in the statement `let y = 6;` is an
statements: in [Listing 3-1][Listing-3-1], the `6` in the statement `let y = 6;` is an
expression that evaluates to the value `6`. Calling a function is an
expression. Calling a macro is an expression. The block that we use to create
new scopes, `{}`, is an expression, for example:
@ -342,3 +345,5 @@ the empty tuple. Therefore, nothing is returned, which contradicts the function
definition and results in an error. In this output, Rust provides a message to
possibly help rectify this issue: it suggests removing the semicolon, which
would fix the error.
[Listing-3-1]: ch03-03-how-functions-work.html#Listing-3-1

View File

@ -172,10 +172,13 @@ Rust branching construct called `match` for these cases.
#### Using `if` in a `let` Statement
Because `if` is an expression, we can use it on the right side of a `let`
statement, as in Listing 3-2.
statement, as in [Listing 3-2][Listing-3-2].
<span class="filename">Filename: src/main.rs</span>
[Listing-3-2]: #Listing-3-2
<a name="Listing-3-2"></a>
```rust
fn main() {
let condition = true;
@ -207,7 +210,7 @@ Remember that blocks of code evaluate to the last expression in them, and
numbers by themselves are also expressions. In this case, the value of the
whole `if` expression depends on which block of code executes. This means the
values that have the potential to be results from each arm of the `if` must be
the same type; in Listing 3-2, the results of both the `if` arm and the `else`
the same type; in [Listing 3-2][Listing-3-2], the results of both the `if` arm and the `else`
arm were `i32` integers. If the types are mismatched, as in the following
example, well get an error:
@ -319,12 +322,15 @@ using a combination of `loop`, `if`, `else`, and `break`; you could try that
now in a program, if youd like.
However, this pattern is so common that Rust has a built-in language construct
for it, called a `while` loop. Listing 3-3 uses `while`: the program loops
for it, called a `while` loop. [Listing 3-3][Listing-3-3] uses `while`: the program loops
three times, counting down each time, and then, after the loop, it prints
another message and exits.
<span class="filename">Filename: src/main.rs</span>
[Listing-3-3]: #Listing-3-3
<a name="Listing-3-3"></a>
```rust
fn main() {
let mut number = 3;
@ -349,10 +355,13 @@ true, the code runs; otherwise, it exits the loop.
#### Looping Through a Collection with `for`
You could use the `while` construct to loop over the elements of a collection,
such as an array. For example, lets look at Listing 3-4.
such as an array. For example, lets look at [Listing 3-4][Listing-3-4].
<span class="filename">Filename: src/main.rs</span>
[Listing-3-4]: #Listing-3-4
<a name="Listing-3-4"></a>
```rust
fn main() {
let a = [10, 20, 30, 40, 50];
@ -396,10 +405,13 @@ code to perform the conditional check on every element on every iteration
through the loop.
As a more concise alternative, you can use a `for` loop and execute some code
for each item in a collection. A `for` loop looks like the code in Listing 3-5.
for each item in a collection. A `for` loop looks like the code in [Listing 3-5][Listing-3-5].
<span class="filename">Filename: src/main.rs</span>
[Listing-3-5]: #Listing-3-5
<a name="Listing-3-5"></a>
```rust
fn main() {
let a = [10, 20, 30, 40, 50];
@ -413,12 +425,12 @@ fn main() {
<span class="caption">Listing 3-5: Looping through each element of a collection
using a `for` loop</span>
When we run this code, well see the same output as in Listing 3-4. More
When we run this code, well see the same output as in [Listing 3-4][Listing-3-4]. More
importantly, weve now increased the safety of the code and eliminated the
chance of bugs that might result from going beyond the end of the array or not
going far enough and missing some items.
For example, in the code in Listing 3-4, if you removed an item from the `a`
For example, in the code in [Listing 3-4][Listing-3-4], if you removed an item from the `a`
array but forgot to update the condition to `while index < 4`, the code would
panic. Using the `for` loop, you wouldnt need to remember to change any other
code if you changed the number of values in the array.
@ -426,7 +438,7 @@ code if you changed the number of values in the array.
The safety and conciseness of `for` loops make them the most commonly used loop
construct in Rust. Even in situations in which you want to run some code a
certain number of times, as in the countdown example that used a `while` loop
in Listing 3-3, most Rustaceans would use a `for` loop. The way to do that
in [Listing 3-3][Listing-3-3], most Rustaceans would use a `for` loop. The way to do that
would be to use a `Range`, which is a type provided by the standard library
that generates all numbers in sequence starting from one number and ending
before another number.
@ -461,3 +473,8 @@ programs to do the following:
When youre ready to move on, well talk about a concept in Rust that *doesnt*
commonly exist in other programming languages: ownership.
[Listing-3-2]: ch03-05-control-flow.html#Listing-3-2
[Listing-3-3]: ch03-05-control-flow.html#Listing-3-3
[Listing-3-4]: ch03-05-control-flow.html#Listing-3-4
[Listing-3-5]: ch03-05-control-flow.html#Listing-3-5

View File

@ -110,9 +110,12 @@ let s = "hello";
The variable `s` refers to a string literal, where the value of the string is
hardcoded into the text of our program. The variable is valid from the point at
which its declared until the end of the current *scope*. Listing 4-1 has
which its declared until the end of the current *scope*. [Listing 4-1][Listing-4-1] has
comments annotating where the variable `s` is valid.
[Listing-4-1]: #Listing-4-1
<a name="Listing-4-1"></a>
```rust
{ // s is not valid here, its not yet declared
let s = "hello"; // s is valid from this point forward
@ -211,7 +214,7 @@ We need to pair exactly one `allocate` with exactly one `free`.
Rust takes a different path: the memory is automatically returned once the
variable that owns it goes out of scope. Heres a version of our scope example
from Listing 4-1 using a `String` instead of a string literal:
from [Listing 4-1][Listing-4-1] using a `String` instead of a string literal:
```rust
{
@ -241,7 +244,10 @@ weve allocated on the heap. Lets explore some of those situations now.
#### Ways Variables and Data Interact: Move
Multiple variables can interact with the same data in different ways in Rust.
Lets look at an example using an integer in Listing 4-2.
Lets look at an example using an integer in [Listing 4-2][Listing-4-2].
[Listing-4-2]: #Listing-4-2
<a name="Listing-4-2"></a>
```rust
let x = 5;
@ -268,12 +274,15 @@ This looks very similar to the previous code, so we might assume that the way
it works would be the same: that is, the second line would make a copy of the
value in `s1` and bind it to `s2`. But this isnt quite what happens.
Take a look at Figure 4-1 to see what is happening to `String` under the
Take a look at [Figure 4-1][Figure-4-1] to see what is happening to `String` under the
covers. A `String` is made up of three parts, shown on the left: a pointer to
the memory that holds the contents of the string, a length, and a capacity.
This group of data is stored on the stack. On the right is the memory on the
heap that holds the contents.
[Figure-4-1]: #Figure-4-1
<a name="Figure-4-1"></a>
<img alt="String in memory" src="img/trpl04-01.svg" class="center" style="width: 50%;" />
<span class="caption">Figure 4-1: Representation in memory of a `String`
@ -288,18 +297,24 @@ the capacity.
When we assign `s1` to `s2`, the `String` data is copied, meaning we copy the
pointer, the length, and the capacity that are on the stack. We do not copy the
data on the heap that the pointer refers to. In other words, the data
representation in memory looks like Figure 4-2.
representation in memory looks like [Figure 4-2][Figure-4-2].
[Figure-4-2]: #Figure-4-2
<a name="Figure-4-2"></a>
<img alt="s1 and s2 pointing to the same value" src="img/trpl04-02.svg" class="center" style="width: 50%;" />
<span class="caption">Figure 4-2: Representation in memory of the variable `s2`
that has a copy of the pointer, length, and capacity of `s1`</span>
The representation does *not* look like Figure 4-3, which is what memory would
The representation does *not* look like [Figure 4-3][Figure-4-3], which is what memory would
look like if Rust instead copied the heap data as well. If Rust did this, the
operation `s2 = s1` could be very expensive in terms of runtime performance if
the data on the heap were large.
[Figure-4-3]: #Figure-4-3
<a name="Figure-4-3"></a>
<img alt="s1 and s2 to two places" src="img/trpl04-03.svg" class="center" style="width: 50%;" />
<span class="caption">Figure 4-3: Another possibility for what `s2 = s1` might
@ -307,7 +322,7 @@ do if Rust copied the heap data as well</span>
Earlier, we said that when a variable goes out of scope, Rust automatically
calls the `drop` function and cleans up the heap memory for that variable. But
Figure 4-2 shows both data pointers pointing to the same location. This is a
[Figure 4-2][Figure-4-2] shows both data pointers pointing to the same location. This is a
problem: when `s2` and `s1` go out of scope, they will both try to free the
same memory. This is known as a *double free* error and is one of the memory
safety bugs we mentioned previously. Freeing memory twice can lead to memory
@ -348,7 +363,10 @@ other languages, the concept of copying the pointer, length, and capacity
without copying the data probably sounds like making a shallow copy. But
because Rust also invalidates the first variable, instead of being called a
shallow copy, its known as a *move*. In this example, we would say that `s1`
was *moved* into `s2`. So what actually happens is shown in Figure 4-4.
was *moved* into `s2`. So what actually happens is shown in [Figure 4-4][Figure-4-4].
[Figure-4-4]: #Figure-4-4
<a name="Figure-4-4"></a>
<img alt="s1 moved to s2" src="img/trpl04-04.svg" class="center" style="width: 50%;" />
@ -378,7 +396,7 @@ let s2 = s1.clone();
println!("s1 = {}, s2 = {}", s1, s2);
```
This works just fine and explicitly produces the behavior shown in Figure 4-3,
This works just fine and explicitly produces the behavior shown in [Figure 4-3][Figure-4-3],
where the heap data *does* get copied.
When you see a call to `clone`, you know that some arbitrary code is being
@ -388,7 +406,7 @@ different is going on.
#### Stack-Only Data: Copy
Theres another wrinkle we havent talked about yet. This code using integers,
part of which was shown in Listing 4-2, works and is valid:
part of which was shown in [Listing 4-2][Listing-4-2], works and is valid:
```rust
let x = 5;
@ -433,11 +451,14 @@ be sure, but as a general rule, any group of simple scalar values can be
The semantics for passing a value to a function are similar to those for
assigning a value to a variable. Passing a variable to a function will move or
copy, just as assignment does. Listing 4-3 has an example with some annotations
copy, just as assignment does. [Listing 4-3][Listing-4-3] has an example with some annotations
showing where variables go into and out of scope.
<span class="filename">Filename: src/main.rs</span>
[Listing-4-3]: #Listing-4-3
<a name="Listing-4-3"></a>
```rust
fn main() {
let s = String::from("hello"); // s comes into scope
@ -474,11 +495,14 @@ the ownership rules prevent you from doing so.
### Return Values and Scope
Returning values can also transfer ownership. Listing 4-4 is an example with
similar annotations to those in Listing 4-3.
Returning values can also transfer ownership. [Listing 4-4][Listing-4-4] is an example with
similar annotations to those in [Listing 4-3][Listing-4-3].
<span class="filename">Filename: src/main.rs</span>
[Listing-4-4]: #Listing-4-4
<a name="Listing-4-4"></a>
```rust
fn main() {
let s1 = gives_ownership(); // gives_ownership moves its return
@ -525,10 +549,13 @@ Its quite annoying that anything we pass in also needs to be passed back if w
want to use it again, in addition to any data resulting from the body of the
function that we might want to return as well.
Its possible to return multiple values using a tuple, as shown in Listing 4-5.
Its possible to return multiple values using a tuple, as shown in [Listing 4-5][Listing-4-5].
<span class="filename">Filename: src/main.rs</span>
[Listing-4-5]: #Listing-4-5
<a name="Listing-4-5"></a>
```rust
fn main() {
let s1 = String::from("hello");
@ -550,3 +577,13 @@ fn calculate_length(s: String) -> (String, usize) {
But this is too much ceremony and a lot of work for a concept that should be
common. Luckily for us, Rust has a feature for this concept, called
*references*.
[Listing-4-1]: ch04-01-what-is-ownership.html#Listing-4-1
[Listing-4-2]: ch04-01-what-is-ownership.html#Listing-4-2
[Figure-4-1]: ch04-01-what-is-ownership.html#Figure-4-1
[Figure-4-2]: ch04-01-what-is-ownership.html#Figure-4-2
[Figure-4-3]: ch04-01-what-is-ownership.html#Figure-4-3
[Figure-4-4]: ch04-01-what-is-ownership.html#Figure-4-4
[Listing-4-3]: ch04-01-what-is-ownership.html#Listing-4-3
[Listing-4-4]: ch04-01-what-is-ownership.html#Listing-4-4
[Listing-4-5]: ch04-01-what-is-ownership.html#Listing-4-5

View File

@ -1,6 +1,6 @@
## References and Borrowing
The issue with the tuple code in Listing 4-5 is that we have to return the
The issue with the tuple code in [Listing 4-5][Listing-4-5] is that we have to return the
`String` to the calling function so we can still use the `String` after the
call to `calculate_length`, because the `String` was moved into
`calculate_length`.
@ -31,7 +31,10 @@ function return value is gone. Second, note that we pass `&s1` into
`String`.
These ampersands are *references*, and they allow you to refer to some value
without taking ownership of it. Figure 4-5 shows a diagram.
without taking ownership of it. [Figure 4-5][Figure-4-5] shows a diagram.
[Figure-4-5]: #Figure-4-5
<a name="Figure-4-5"></a>
<img alt="&String s pointing at String s1" src="img/trpl04-05.svg" class="center" />
@ -79,10 +82,13 @@ if a person owns something, you can borrow it from them. When youre done, you
have to give it back.
So what happens if we try to modify something were borrowing? Try the code in
Listing 4-6. Spoiler alert: it doesnt work!
[Listing 4-6][Listing-4-6]. Spoiler alert: it doesnt work!
<span class="filename">Filename: src/main.rs</span>
[Listing-4-6]: #Listing-4-6
<a name="Listing-4-6"></a>
```rust,ignore
fn main() {
let s = String::from("hello");
@ -114,7 +120,7 @@ allowed to modify something we have a reference to.
### Mutable References
We can fix the error in the code from Listing 4-6 with just a small tweak:
We can fix the error in the code from [Listing 4-6][Listing-4-6] with just a small tweak:
<span class="filename">Filename: src/main.rs</span>
@ -319,3 +325,7 @@ Lets recap what weve discussed about references:
* References must always be valid.
Next, well look at a different kind of reference: slices.
[Listing-4-5]: ch04-01-what-is-ownership.html#Listing-4-5
[Figure-4-5]: ch04-02-references-and-borrowing.html#Figure-4-5
[Listing-4-6]: ch04-02-references-and-borrowing.html#Listing-4-6

View File

@ -18,10 +18,13 @@ fn first_word(s: &String) -> ?
This function, `first_word`, has a `&String` as a parameter. We dont want
ownership, so this is fine. But what should we return? We dont really have a
way to talk about *part* of a string. However, we could return the index of the
end of the word. Lets try that, as shown in Listing 4-7.
end of the word. Lets try that, as shown in [Listing 4-7][Listing-4-7].
<span class="filename">Filename: src/main.rs</span>
[Listing-4-7]: #Listing-4-7
<a name="Listing-4-7"></a>
```rust
fn first_word(s: &String) -> usize {
let bytes = s.as_bytes();
@ -83,11 +86,14 @@ We now have a way to find out the index of the end of the first word in the
string, but theres a problem. Were returning a `usize` on its own, but its
only a meaningful number in the context of the `&String`. In other words,
because its a separate value from the `String`, theres no guarantee that it
will still be valid in the future. Consider the program in Listing 4-8 that
uses the `first_word` function from Listing 4-7.
will still be valid in the future. Consider the program in [Listing 4-8][Listing-4-8] that
uses the `first_word` function from [Listing 4-7][Listing-4-7].
<span class="filename">Filename: src/main.rs</span>
[Listing-4-8]: #Listing-4-8
<a name="Listing-4-8"></a>
```rust
# fn first_word(s: &String) -> usize {
# let bytes = s.as_bytes();
@ -161,7 +167,10 @@ the length of the slice, which corresponds to `ending_index` minus
`starting_index`. So in the case of `let world = &s[6..11];`, `world` would be
a slice that contains a pointer to the 7th byte of `s` with a length value of 5.
Figure 4-6 shows this in a diagram.
[Figure 4-6][Figure-4-6] shows this in a diagram.
[Figure-4-6]: #Figure-4-6
<a name="Figure-4-6"></a>
<img alt="world containing a pointer to the 6th byte of String s and a length 5" src="img/trpl04-06.svg" class="center" style="width: 50%;" />
@ -228,8 +237,8 @@ fn first_word(s: &String) -> &str {
}
```
We get the index for the end of the word in the same way as we did in Listing
4-7, by looking for the first occurrence of a space. When we find a space, we
We get the index for the end of the word in the same way as we did in [Listing 4-7][Listing-4-7],
by looking for the first occurrence of a space. When we find a space, we
return a string slice using the start of the string and the index of the space
as the starting and ending indices.
@ -245,7 +254,7 @@ fn second_word(s: &String) -> &str {
We now have a straightforward API thats much harder to mess up, because the
compiler will ensure the references into the `String` remain valid. Remember
the bug in the program in Listing 4-8, when we got the index to the end of the
the bug in the program in [Listing 4-8][Listing-4-8], when we got the index to the end of the
first word but then cleared the string so our index was invalid? That code was
logically incorrect but didnt show any immediate errors. The problems would
show up later if we kept trying to use the first word index with an emptied
@ -308,10 +317,13 @@ one more improvement on `first_word`, and thats its signature:
fn first_word(s: &String) -> &str {
```
A more experienced Rustacean would write the signature shown in Listing 4-9
A more experienced Rustacean would write the signature shown in [Listing 4-9][Listing-4-9]
instead because it allows us to use the same function on both `String` values
and `&str` values.
[Listing-4-9]: #Listing-4-9
<a name="Listing-4-9"></a>
```rust,ignore
fn first_word(s: &str) -> &str {
```
@ -389,3 +401,8 @@ means you dont have to write and debug extra code to get this control.
Ownership affects how lots of other parts of Rust work, so well talk about
these concepts further throughout the rest of the book. Lets move on to
Chapter 5 and look at grouping pieces of data together in a `struct`.
[Listing-4-7]: ch04-03-slices.html#Listing-4-7
[Listing-4-8]: ch04-03-slices.html#Listing-4-8
[Figure-4-6]: ch04-03-slices.html#Figure-4-6
[Listing-4-9]: ch04-03-slices.html#Listing-4-9

View File

@ -9,9 +9,12 @@ order of the data to specify or access the values of an instance.
To define a struct, we enter the keyword `struct` and name the entire struct. A
structs name should describe the significance of the pieces of data being
grouped together. Then, inside curly brackets, we define the names and types of
the pieces of data, which we call *fields*. For example, Listing 5-1 shows a
the pieces of data, which we call *fields*. For example, [Listing 5-1][Listing-5-1] shows a
struct that stores information about a user account.
[Listing-5-1]: #Listing-5-1
<a name="Listing-5-1"></a>
```rust
struct User {
username: String,
@ -31,7 +34,10 @@ data we want to store in those fields. We dont have to specify the fields in
the same order in which we declared them in the struct. In other words, the
struct definition is like a general template for the type, and instances fill
in that template with particular data to create values of the type. For
example, we can declare a particular user as shown in Listing 5-2.
example, we can declare a particular user as shown in [Listing 5-2][Listing-5-2].
[Listing-5-2]: #Listing-5-2
<a name="Listing-5-2"></a>
```rust
# struct User {
@ -55,9 +61,12 @@ struct</span>
To get a specific value from a struct, we can use dot notation. If we wanted
just this users email address, we could use `user1.email` wherever we wanted
to use this value. If the instance is mutable, we can change a value by using
the dot notation and assigning into a particular field. Listing 5-3 shows how
the dot notation and assigning into a particular field. [Listing 5-3][Listing-5-3] shows how
to change the value in the `email` field of a mutable `User` instance.
[Listing-5-3]: #Listing-5-3
<a name="Listing-5-3"></a>
```rust
# struct User {
# username: String,
@ -84,10 +93,13 @@ only certain fields as mutable. As with any expression, we can construct a new
instance of the struct as the last expression in the function body to
implicitly return that new instance.
Listing 5-4 shows a `build_user` function that returns a `User` instance with
[Listing 5-4][Listing-5-4] shows a `build_user` function that returns a `User` instance with
the given email and username. The `active` field gets the value of `true`, and
the `sign_in_count` gets a value of `1`.
[Listing-5-4]: #Listing-5-4
<a name="Listing-5-4"></a>
```rust
# struct User {
# username: String,
@ -117,9 +129,12 @@ would get even more annoying. Luckily, theres a convenient shorthand!
### Using the Field Init Shorthand when Variables and Fields Have the Same Name
Because the parameter names and the struct field names are exactly the same in
Listing 5-4, we can use the *field init shorthand* syntax to rewrite
[Listing 5-4][Listing-5-4], we can use the *field init shorthand* syntax to rewrite
`build_user` so that it behaves exactly the same but doesnt have the
repetition of `email` and `username`, as shown in Listing 5-5.
repetition of `email` and `username`, as shown in [Listing 5-5][Listing-5-5].
[Listing-5-5]: #Listing-5-5
<a name="Listing-5-5"></a>
```rust
# struct User {
@ -154,9 +169,12 @@ than `email: email`.
Its often useful to create a new instance of a struct that uses most of an old
instances values but changes some. Youll do this using *struct update syntax*.
First, Listing 5-6 shows how we create a new `User` instance in `user2` without
First, [Listing 5-6][Listing-5-6] shows how we create a new `User` instance in `user2` without
the update syntax. We set new values for `email` and `username` but otherwise
use the same values from `user1` that we created in Listing 5-2.
use the same values from `user1` that we created in [Listing 5-2][Listing-5-2].
[Listing-5-6]: #Listing-5-6
<a name="Listing-5-6"></a>
```rust
# struct User {
@ -185,9 +203,12 @@ let user2 = User {
the values from `user1`</span>
Using struct update syntax, we can achieve the same effect with less code, as
shown in Listing 5-7. The syntax `..` specifies that the remaining fields not
shown in [Listing 5-7][Listing-5-7]. The syntax `..` specifies that the remaining fields not
explicitly set should have the same value as the fields in the given instance.
[Listing-5-7]: #Listing-5-7
<a name="Listing-5-7"></a>
```rust
# struct User {
# username: String,
@ -214,7 +235,7 @@ let user2 = User {
`email` and `username` values for a `User` instance but use the rest of the
values from the fields of the instance in the `user1` variable</span>
The code in Listing 5-7 also creates an instance in `user2` that has a
The code in [Listing 5-7][Listing-5-7] also creates an instance in `user2` that has a
different value for `email` and `username` but has the same values for the
`active` and `sign_in_count` fields from `user1`.
@ -258,7 +279,7 @@ itself. Well discuss traits in Chapter 10.
> ### Ownership of Struct Data
>
> In the `User` struct definition in Listing 5-1, we used the owned `String`
> In the `User` struct definition in [Listing 5-1][Listing-5-1], we used the owned `String`
> type rather than the `&str` string slice type. This is a deliberate choice
> because we want instances of this struct to own all of its data and for that
> data to be valid for as long as the entire struct is valid.
@ -308,3 +329,11 @@ itself. Well discuss traits in Chapter 10.
> In Chapter 10, well discuss how to fix these errors so you can store
> references in structs, but for now, well fix errors like these using owned
> types like `String` instead of references like `&str`.
[Listing-5-1]: ch05-01-defining-structs.html#Listing-5-1
[Listing-5-2]: ch05-01-defining-structs.html#Listing-5-2
[Listing-5-3]: ch05-01-defining-structs.html#Listing-5-3
[Listing-5-4]: ch05-01-defining-structs.html#Listing-5-4
[Listing-5-5]: ch05-01-defining-structs.html#Listing-5-5
[Listing-5-6]: ch05-01-defining-structs.html#Listing-5-6
[Listing-5-7]: ch05-01-defining-structs.html#Listing-5-7

View File

@ -6,11 +6,14 @@ refactor the program until were using structs instead.
Lets make a new binary project with Cargo called *rectangles* that will take
the width and height of a rectangle specified in pixels and calculate the area
of the rectangle. Listing 5-8 shows a short program with one way of doing
of the rectangle. [Listing 5-8][Listing-5-8] shows a short program with one way of doing
exactly that in our projects *src/main.rs*.
<span class="filename">Filename: src/main.rs</span>
[Listing-5-8]: #Listing-5-8
<a name="Listing-5-8"></a>
```rust
fn main() {
let width1 = 30;
@ -36,7 +39,7 @@ Now, run this program using `cargo run`:
The area of the rectangle is 1500 square pixels.
```
Even though Listing 5-8 works and figures out the area of the rectangle by
Even though [Listing 5-8][Listing-5-8] works and figures out the area of the rectangle by
calling the `area` function with each dimension, we can do better. The width
and the height are related to each other because together they describe one
rectangle.
@ -55,10 +58,13 @@ we might do that in “The Tuple Type” section of Chapter 3: by using tuples.
### Refactoring with Tuples
Listing 5-9 shows another version of our program that uses tuples.
[Listing 5-9][Listing-5-9] shows another version of our program that uses tuples.
<span class="filename">Filename: src/main.rs</span>
[Listing-5-9]: #Listing-5-9
<a name="Listing-5-9"></a>
```rust
fn main() {
let rect1 = (30, 50);
@ -94,10 +100,13 @@ our code.
We use structs to add meaning by labeling the data. We can transform the tuple
were using into a data type with a name for the whole as well as names for the
parts, as shown in Listing 5-10.
parts, as shown in [Listing 5-10][Listing-5-10].
<span class="filename">Filename: src/main.rs</span>
[Listing-5-10]: #Listing-5-10
<a name="Listing-5-10"></a>
```rust
struct Rectangle {
width: u32,
@ -142,12 +151,15 @@ and `1`. This is a win for clarity.
### Adding Useful Functionality with Derived Traits
Itd be nice to be able to print an instance of `Rectangle` while were
debugging our program and see the values for all its fields. Listing 5-11 tries
debugging our program and see the values for all its fields. [Listing 5-11][Listing-5-11] tries
using the `println!` macro as we have used in previous chapters. This wont
work, however.
<span class="filename">Filename: src/main.rs</span>
[Listing-5-11]: #Listing-5-11
<a name="Listing-5-11"></a>
```rust,ignore
struct Rectangle {
width: u32,
@ -210,10 +222,13 @@ crate, add `#[derive(Debug)]` or manually implement it
Rust *does* include functionality to print out debugging information, but we
have to explicitly opt in to make that functionality available for our struct.
To do that, we add the annotation `#[derive(Debug)]` just before the struct
definition, as shown in Listing 5-12.
definition, as shown in [Listing 5-12][Listing-5-12].
<span class="filename">Filename: src/main.rs</span>
[Listing-5-12]: #Listing-5-12
<a name="Listing-5-12"></a>
```rust
#[derive(Debug)]
struct Rectangle {
@ -261,3 +276,9 @@ It would be helpful to tie this behavior more closely to our `Rectangle`
struct, because it wont work with any other type. Lets look at how we can
continue to refactor this code by turning the `area` function into an `area`
*method* defined on our `Rectangle` type.
[Listing-5-8]: ch05-02-example-structs.html#Listing-5-8
[Listing-5-9]: ch05-02-example-structs.html#Listing-5-9
[Listing-5-10]: ch05-02-example-structs.html#Listing-5-10
[Listing-5-11]: ch05-02-example-structs.html#Listing-5-11
[Listing-5-12]: ch05-02-example-structs.html#Listing-5-12

View File

@ -12,10 +12,13 @@ instance of the struct the method is being called on.
Lets change the `area` function that has a `Rectangle` instance as a parameter
and instead make an `area` method defined on the `Rectangle` struct, as shown
in Listing 5-13.
in [Listing 5-13][Listing-5-13].
<span class="filename">Filename: src/main.rs</span>
[Listing-5-13]: #Listing-5-13
<a name="Listing-5-13"></a>
```rust
#[derive(Debug)]
struct Rectangle {
@ -124,11 +127,14 @@ Lets practice using methods by implementing a second method on the `Rectangle
struct. This time, we want an instance of `Rectangle` to take another instance
of `Rectangle` and return `true` if the second `Rectangle` can fit completely
within `self`; otherwise it should return `false`. That is, we want to be able
to write the program shown in Listing 5-14, once weve defined the `can_hold`
to write the program shown in [Listing 5-14][Listing-5-14], once weve defined the `can_hold`
method.
<span class="filename">Filename: src/main.rs</span>
[Listing-5-14]: #Listing-5-14
<a name="Listing-5-14"></a>
```rust,ignore
fn main() {
let rect1 = Rectangle { width: 30, height: 50 };
@ -164,10 +170,13 @@ calling the `can_hold` method. The return value of `can_hold` will be a
Boolean, and the implementation will check whether the width and height of
`self` are both greater than the width and height of the other `Rectangle`,
respectively. Lets add the new `can_hold` method to the `impl` block from
Listing 5-13, shown in Listing 5-15.
[Listing 5-13][Listing-5-13], shown in [Listing 5-15][Listing-5-15].
<span class="filename">Filename: src/main.rs</span>
[Listing-5-15]: #Listing-5-15
<a name="Listing-5-15"></a>
```rust
# #[derive(Debug)]
# struct Rectangle {
@ -189,7 +198,7 @@ impl Rectangle {
<span class="caption">Listing 5-15: Implementing the `can_hold` method on
`Rectangle` that takes another `Rectangle` instance as a parameter</span>
When we run this code with the `main` function in Listing 5-14, well get our
When we run this code with the `main` function in [Listing 5-14][Listing-5-14], well get our
desired output. Methods can take multiple parameters that we add to the
signature after the `self` parameter, and those parameters work just like
parameters in functions.
@ -232,10 +241,13 @@ namespaces created by modules. Well discuss modules in Chapter 7.
### Multiple `impl` Blocks
Each struct is allowed to have multiple `impl` blocks. For example, Listing
5-15 is equivalent to the code shown in Listing 5-16, which has each method
Each struct is allowed to have multiple `impl` blocks. For example, [Listing 5-15][Listing-5-15]
is equivalent to the code shown in [Listing 5-16][Listing-5-16], which has each method
in its own `impl` block.
[Listing-5-16]: #Listing-5-16
<a name="Listing-5-16"></a>
```rust
# #[derive(Debug)]
# struct Rectangle {
@ -256,7 +268,7 @@ impl Rectangle {
}
```
<span class="caption">Listing 5-16: Rewriting Listing 5-15 using multiple `impl`
<span class="caption">Listing 5-16: Rewriting [Listing 5-15][Listing-5-15] using multiple `impl`
blocks</span>
Theres no reason to separate these methods into multiple `impl` blocks here,
@ -274,3 +286,8 @@ instance available.
But structs arent the only way you can create custom types: lets turn to
Rusts enum feature to add another tool to your toolbox.
[Listing-5-13]: ch05-03-method-syntax.html#Listing-5-13
[Listing-5-14]: ch05-03-method-syntax.html#Listing-5-14
[Listing-5-15]: ch05-03-method-syntax.html#Listing-5-15
[Listing-5-16]: ch05-03-method-syntax.html#Listing-5-16

View File

@ -73,7 +73,10 @@ route(IpAddrKind::V6);
Using enums has even more advantages. Thinking more about our IP address type,
at the moment we dont have a way to store the actual IP address *data*; we
only know what *kind* it is. Given that you just learned about structs in
Chapter 5, you might tackle this problem as shown in Listing 6-1.
Chapter 5, you might tackle this problem as shown in [Listing 6-1][Listing-6-1].
[Listing-6-1]: #Listing-6-1
<a name="Listing-6-1"></a>
```rust
enum IpAddrKind {
@ -182,9 +185,12 @@ we can still create and use our own definition without conflict because we
havent brought the standard librarys definition into our scope. Well talk
more about bringing types into scope in Chapter 7.
Lets look at another example of an enum in Listing 6-2: this one has a wide
Lets look at another example of an enum in [Listing 6-2][Listing-6-2]: this one has a wide
variety of types embedded in its variants.
[Listing-6-2]: #Listing-6-2
<a name="Listing-6-2"></a>
```rust
enum Message {
Quit,
@ -204,7 +210,7 @@ This enum has four variants with different types:
* `Write` includes a single `String`.
* `ChangeColor` includes three `i32` values.
Defining an enum with variants such as the ones in Listing 6-2 is similar to
Defining an enum with variants such as the ones in [Listing 6-2][Listing-6-2] is similar to
defining different kinds of struct definitions, except the enum doesnt use the
`struct` keyword and all the variants are grouped together under the `Message`
type. The following structs could hold the same data that the preceding enum
@ -222,7 +228,7 @@ struct ChangeColorMessage(i32, i32, i32); // tuple struct
But if we used the different structs, which each have their own type, we
couldnt as easily define a function to take any of these kinds of messages as
we could with the `Message` enum defined in Listing 6-2, which is a single type.
we could with the `Message` enum defined in [Listing 6-2][Listing-6-2], which is a single type.
There is one more similarity between enums and structs: just as were able to
define methods on structs using `impl`, were also able to define methods on
@ -397,3 +403,6 @@ value available. The `match` expression is a control flow construct that does
just this when used with enums: it will run different code depending on which
variant of the enum it has, and that code can use the data inside the matching
value.
[Listing-6-1]: ch06-01-defining-an-enum.html#Listing-6-1
[Listing-6-2]: ch06-01-defining-an-enum.html#Listing-6-2

View File

@ -17,7 +17,10 @@ the value falls into the associated code block to be used during execution.
Because we just mentioned coins, lets use them as an example using `match`! We
can write a function that can take an unknown United States coin and, in a
similar way as the counting machine, determine which coin it is and return its
value in cents, as shown here in Listing 6-3.
value in cents, as shown here in [Listing 6-3][Listing-6-3].
[Listing-6-3]: #Listing-6-3
<a name="Listing-6-3"></a>
```rust
enum Coin {
@ -56,14 +59,14 @@ When the `match` expression executes, it compares the resulting value against
the pattern of each arm, in order. If a pattern matches the value, the code
associated with that pattern is executed. If that pattern doesnt match the
value, execution continues to the next arm, much as in a coin-sorting machine.
We can have as many arms as we need: in Listing 6-3, our `match` has four arms.
We can have as many arms as we need: in [Listing 6-3][Listing-6-3], our `match` has four arms.
The code associated with each arm is an expression, and the resulting value of
the expression in the matching arm is the value that gets returned for the
entire `match` expression.
Curly brackets typically arent used if the match arm code is short, as it is
in Listing 6-3 where each arm just returns a value. If you want to run multiple
in [Listing 6-3][Listing-6-3] where each arm just returns a value. If you want to run multiple
lines of code in a match arm, you can use curly brackets. For example, the
following code would print “Lucky penny!” every time the method was called with
a `Coin::Penny` but would still return the last value of the block, `1`:
@ -100,7 +103,10 @@ From 1999 through 2008, the United States minted quarters with different
designs for each of the 50 states on one side. No other coins got state
designs, so only quarters have this extra value. We can add this information to
our `enum` by changing the `Quarter` variant to include a `UsState` value stored
inside it, which weve done here in Listing 6-4.
inside it, which weve done here in [Listing 6-4][Listing-6-4].
[Listing-6-4]: #Listing-6-4
<a name="Listing-6-4"></a>
```rust
#[derive(Debug)] // so we can inspect the state in a minute
@ -179,7 +185,10 @@ the function should return the `None` value and not attempt to perform any
operations.
This function is very easy to write, thanks to `match`, and will look like
Listing 6-5.
[Listing 6-5][Listing-6-5].
[Listing-6-5]: #Listing-6-5
<a name="Listing-6-5"></a>
```rust
fn plus_one(x: Option<i32>) -> Option<i32> {
@ -217,7 +226,7 @@ Does `Some(5)` match `Some(i)`? Why yes it does! We have the same variant. The
code in the match arm is then executed, so we add 1 to the value of `i` and
create a new `Some` value with our total `6` inside.
Now lets consider the second call of `plus_one` in Listing 6-5, where `x` is
Now lets consider the second call of `plus_one` in [Listing 6-5][Listing-6-5], where `x` is
`None`. We enter the `match` and compare to the first arm.
```rust,ignore
@ -293,3 +302,7 @@ list before the `_` placeholder.
However, the `match` expression can be a bit wordy in a situation in which we
care about only *one* of the cases. For this situation, Rust provides `if let`.
[Listing-6-3]: ch06-02-match.html#Listing-6-3
[Listing-6-4]: ch06-02-match.html#Listing-6-4
[Listing-6-5]: ch06-02-match.html#Listing-6-5

View File

@ -2,9 +2,12 @@
The `if let` syntax lets you combine `if` and `let` into a less verbose way to
handle values that match one pattern while ignoring the rest. Consider the
program in Listing 6-6 that matches on an `Option<u8>` value but only wants to
program in [Listing 6-6][Listing-6-6] that matches on an `Option<u8>` value but only wants to
execute code if the value is 3.
[Listing-6-6]: #Listing-6-6
<a name="Listing-6-6"></a>
```rust
let some_u8_value = Some(0u8);
match some_u8_value {
@ -22,7 +25,7 @@ have to add `_ => ()` after processing just one variant, which is a lot of
boilerplate code to add.
Instead, we could write this in a shorter way using `if let`. The following
code behaves the same as the `match` in Listing 6-6:
code behaves the same as the `match` in [Listing 6-6][Listing-6-6]:
```rust
# let some_u8_value = Some(0u8);
@ -47,7 +50,7 @@ runs code when the value matches one pattern and then ignores all other values.
We can include an `else` with an `if let`. The block of code that goes with the
`else` is the same as the block of code that would go with the `_` case in the
`match` expression that is equivalent to the `if let` and `else`. Recall the
`Coin` enum definition in Listing 6-4, where the `Quarter` variant also held a
`Coin` enum definition in [Listing 6-4][Listing-6-4], where the `Quarter` variant also held a
`UsState` value. If we wanted to count all non-quarter coins we see while also
announcing the state of the quarters, we could do that with a `match`
expression like this:
@ -116,3 +119,6 @@ function expects.
In order to provide a well-organized API to your users that is straightforward
to use and only exposes exactly what your users will need, lets now turn to
Rusts modules.
[Listing-6-6]: ch06-03-if-let.html#Listing-6-6
[Listing-6-4]: ch06-02-match.html#Listing-6-4

View File

@ -70,10 +70,13 @@ would need to specify the module and use the namespace syntax `::` like so:
We can also have multiple modules, side by side, in the same *src/lib.rs* file.
For example, to also have a `client` module that has a function named
`connect`, we can add it as shown in Listing 7-1.
`connect`, we can add it as shown in [Listing 7-1][Listing-7-1].
<span class="filename">Filename: src/lib.rs</span>
[Listing-7-1]: #Listing-7-1
<a name="Listing-7-1"></a>
```rust
mod network {
fn connect() {
@ -103,10 +106,13 @@ related functionality organized together and separate functionality apart. The
way you choose to organize your code depends on how you think about the
relationship between the parts of your code. For instance, the `client` code
and its `connect` function might make more sense to users of our library if
they were inside the `network` namespace instead, as in Listing 7-2.
they were inside the `network` namespace instead, as in [Listing 7-2][Listing-7-2].
<span class="filename">Filename: src/lib.rs</span>
[Listing-7-2]: #Listing-7-2
<a name="Listing-7-2"></a>
```rust
mod network {
fn connect() {
@ -123,14 +129,14 @@ mod network {
`network` module</span>
In your *src/lib.rs* file, replace the existing `mod network` and `mod client`
definitions with the ones in Listing 7-2, which have the `client` module as an
definitions with the ones in [Listing 7-2][Listing-7-2], which have the `client` module as an
inner module of `network`. The functions `network::connect` and
`network::client::connect` are both named `connect`, but they dont conflict
with each other because theyre in different namespaces.
In this way, modules form a hierarchy. The contents of *src/lib.rs* are at the
topmost level, and the submodules are at lower levels. Heres what the
organization of our example in Listing 7-1 looks like when thought of as a
organization of our example in [Listing 7-1][Listing-7-1] looks like when thought of as a
hierarchy:
```text
@ -139,7 +145,7 @@ communicator
└── client
```
And heres the hierarchy corresponding to the example in Listing 7-2:
And heres the hierarchy corresponding to the example in [Listing 7-2][Listing-7-2]:
```text
communicator
@ -147,7 +153,7 @@ communicator
└── client
```
The hierarchy shows that in Listing 7-2, `client` is a child of the `network`
The hierarchy shows that in [Listing 7-2][Listing-7-2], `client` is a child of the `network`
module rather than a sibling. More complicated projects can have many modules,
and theyll need to be organized logically in order for you to keep track of
them. What “logically” means in your project is up to you and depends on how
@ -161,10 +167,13 @@ Modules form a hierarchical structure, much like another structure in computing
that youre used to: filesystems! We can use Rusts module system along with
multiple files to split up Rust projects so not everything lives in
*src/lib.rs* or *src/main.rs*. For this example, lets start with the code in
Listing 7-3.
[Listing 7-3][Listing-7-3].
<span class="filename">Filename: src/lib.rs</span>
[Listing-7-3]: #Listing-7-3
<a name="Listing-7-3"></a>
```rust
mod client {
fn connect() {
@ -202,10 +211,13 @@ These would be good reasons to separate the `client`, `network`, and `server`
modules from *src/lib.rs* and place them into their own files.
First, lets replace the `client` module code with only the declaration of the
`client` module so that *src/lib.rs* looks like code shown in Listing 7-4.
`client` module so that *src/lib.rs* looks like code shown in [Listing 7-4][Listing-7-4].
<span class="filename">Filename: src/lib.rs</span>
[Listing-7-4]: #Listing-7-4
<a name="Listing-7-4"></a>
```rust,ignore
mod client;
@ -345,7 +357,10 @@ fn connect() {
}
```
When we try to run `cargo build`, well get the error shown in Listing 7-5.
When we try to run `cargo build`, well get the error shown in [Listing 7-5][Listing-7-5].
[Listing-7-5]: #Listing-7-5
<a name="Listing-7-5"></a>
```text
$ cargo build
@ -375,7 +390,7 @@ The error says we `cannot declare a new module at this location` and is
pointing to the `mod server;` line in *src/network.rs*. So *src/network.rs* is
different than *src/lib.rs* somehow: keep reading to understand why.
The note in the middle of Listing 7-5 is actually very helpful because it
The note in the middle of [Listing 7-5][Listing-7-5] is actually very helpful because it
points out something we havent yet talked about doing:
```text
@ -401,7 +416,7 @@ $ mv src/server.rs src/network
Now when we try to run `cargo build`, compilation will work (well still have
warnings, though). Our module layout still looks exactly the same as it did when
we had all the code in *src/lib.rs* in Listing 7-3:
we had all the code in *src/lib.rs* in [Listing 7-3][Listing-7-3]:
```text
communicator
@ -479,3 +494,9 @@ The modules should be declared in their parent modules file using the `mod`
keyword.
Next, well talk about the `pub` keyword and get rid of those warnings!
[Listing-7-1]: ch07-01-mod-and-the-filesystem.html#Listing-7-1
[Listing-7-2]: ch07-01-mod-and-the-filesystem.html#Listing-7-2
[Listing-7-3]: ch07-01-mod-and-the-filesystem.html#Listing-7-3
[Listing-7-4]: ch07-01-mod-and-the-filesystem.html#Listing-7-4
[Listing-7-5]: ch07-01-mod-and-the-filesystem.html#Listing-7-5

View File

@ -1,6 +1,6 @@
## Controlling Visibility with `pub`
We resolved the error messages shown in Listing 7-5 by moving the `network` and
We resolved the error messages shown in [Listing 7-5][Listing-7-5] by moving the `network` and
`network::server` code into the *src/network/mod.rs* and
*src/network/server.rs* files, respectively. At that point, `cargo build` was
able to build our project, but we still get warning messages saying that the
@ -216,11 +216,14 @@ Overall, these are the rules for item visibility:
### Privacy Examples
Lets look at a few more privacy examples to get some practice. Create a new
library project and enter the code in Listing 7-6 into your new projects
library project and enter the code in [Listing 7-6][Listing-7-6] into your new projects
*src/lib.rs*.
<span class="filename">Filename: src/lib.rs</span>
[Listing-7-6]: #Listing-7-6
<a name="Listing-7-6"></a>
```rust,ignore
mod outermost {
pub fn middle_function() {}
@ -285,3 +288,6 @@ them out!
that we want to refer to the modules starting from the root module.)
Next, lets talk about bringing items into scope with the `use` keyword.
[Listing-7-5]: ch07-01-mod-and-the-filesystem.html#Listing-7-5
[Listing-7-6]: ch07-02-controlling-visibility-with-pub.html#Listing-7-6

View File

@ -2,10 +2,13 @@
Weve covered how to call functions defined within a module using the module
name as part of the call, as in the call to the `nested_modules` function shown
here in Listing 7-7.
here in [Listing 7-7][Listing-7-7].
<span class="filename">Filename: src/main.rs</span>
[Listing-7-7]: #Listing-7-7
<a name="Listing-7-7"></a>
```rust
pub mod a {
pub mod series {
@ -270,3 +273,5 @@ present a tidy public API to your library users.
Next, well look at some collection data structures in the standard library
that you can use in your nice, neat code.
[Listing-7-7]: ch07-03-importing-names-with-use.html#Listing-7-7

View File

@ -9,7 +9,10 @@ lines of text in a file or the prices of items in a shopping cart.
### Creating a New Vector
To create a new, empty vector, we can call the `Vec::new` function, as shown in
Listing 8-1.
[Listing 8-1][Listing-8-1].
[Listing-8-1]: #Listing-8-1
<a name="Listing-8-1"></a>
```rust
let v: Vec<i32> = Vec::new();
@ -24,16 +27,19 @@ store. This is an important point. Vectors are implemented using generics;
well cover how to use generics with your own types in Chapter 10. For now,
know that the `Vec<T>` type provided by the standard library can hold any type,
and when a specific vector holds a specific type, the type is specified within
angle brackets. In Listing 8-1, weve told Rust that the `Vec<T>` in `v` will
angle brackets. In [Listing 8-1][Listing-8-1], weve told Rust that the `Vec<T>` in `v` will
hold elements of the `i32` type.
In more realistic code, Rust can often infer the type of value you want to
store once you insert values, so you rarely need to do this type annotation.
Its more common to create a `Vec<T>` that has initial values, and Rust
provides the `vec!` macro for convenience. The macro will create a new vector
that holds the values you give it. Listing 8-2 creates a new `Vec<i32>` that
that holds the values you give it. [Listing 8-2][Listing-8-2] creates a new `Vec<i32>` that
holds the values `1`, `2`, and `3`.
[Listing-8-2]: #Listing-8-2
<a name="Listing-8-2"></a>
```rust
let v = vec![1, 2, 3];
```
@ -48,7 +54,10 @@ to modify a vector.
### Updating a Vector
To create a vector and then add elements to it, we can use the `push` method,
as shown in Listing 8-3.
as shown in [Listing 8-3][Listing-8-3].
[Listing-8-3]: #Listing-8-3
<a name="Listing-8-3"></a>
```rust
let mut v = Vec::new();
@ -70,7 +79,10 @@ we dont need the `Vec<i32>` annotation.
### Dropping a Vector Drops Its Elements
Like any other `struct`, a vector is freed when it goes out of scope, as
annotated in Listing 8-4.
annotated in [Listing 8-4][Listing-8-4].
[Listing-8-4]: #Listing-8-4
<a name="Listing-8-4"></a>
```rust
{
@ -96,9 +108,12 @@ read their contents is a good next step. There are two ways to reference a
value stored in a vector. In the examples, weve annotated the types of the
values that are returned from these functions for extra clarity.
Listing 8-5 shows both methods of accessing a value in a vector, either with
[Listing 8-5][Listing-8-5] shows both methods of accessing a value in a vector, either with
indexing syntax or the `get` method.
[Listing-8-5]: #Listing-8-5
<a name="Listing-8-5"></a>
```rust
let v = vec![1, 2, 3, 4, 5];
@ -119,7 +134,10 @@ Rust has two ways to reference an element so you can choose how the program
behaves when you try to use an index value that the vector doesnt have an
element for. As an example, lets see what a program will do if it has a vector
that holds five elements and then tries to access an element at index 100, as
shown in Listing 8-6.
shown in [Listing 8-6][Listing-8-6].
[Listing-8-6]: #Listing-8-6
<a name="Listing-8-6"></a>
```rust,should_panic
let v = vec![1, 2, 3, 4, 5];
@ -150,10 +168,13 @@ When the program has a valid reference, the borrow checker enforces the
ownership and borrowing rules (covered in Chapter 4) to ensure this reference
and any other references to the contents of the vector remain valid. Recall the
rule that states you cant have mutable and immutable references in the same
scope. That rule applies in Listing 8-7, where we hold an immutable reference to
scope. That rule applies in [Listing 8-7][Listing-8-7], where we hold an immutable reference to
the first element in a vector and try to add an element to the end, which wont
work.
[Listing-8-7]: #Listing-8-7
<a name="Listing-8-7"></a>
```rust,ignore
let mut v = vec![1, 2, 3, 4, 5];
@ -181,7 +202,7 @@ error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immuta
| - immutable borrow ends here
```
The code in Listing 8-7 might look like it should work: why should a reference
The code in [Listing 8-7][Listing-8-7] might look like it should work: why should a reference
to the first element care about what changes at the end of the vector? This
error is due to the way vectors work: adding a new element onto the end of the
vector might require allocating new memory and copying the old elements to the
@ -196,10 +217,13 @@ programs from ending up in that situation.
### Iterating over the Values in a Vector
If we want to access each element in a vector in turn, we can iterate through
all of the elements rather than use indexes to access one at a time. Listing
8-8 shows how to use a `for` loop to get immutable references to each element
all of the elements rather than use indexes to access one at a time. [Listing 8-8][Listing-8-8]
shows how to use a `for` loop to get immutable references to each element
in a vector of `i32` values and print them.
[Listing-8-8]: #Listing-8-8
<a name="Listing-8-8"></a>
```rust
let v = vec![100, 32, 57];
for i in &v {
@ -211,9 +235,12 @@ for i in &v {
iterating over the elements using a `for` loop</span>
We can also iterate over mutable references to each element in a mutable vector
in order to make changes to all the elements. The `for` loop in Listing 8-9
in order to make changes to all the elements. The `for` loop in [Listing 8-9][Listing-8-9]
will add `50` to each element.
[Listing-8-9]: #Listing-8-9
<a name="Listing-8-9"></a>
```rust
let mut v = vec![100, 32, 57];
for i in &mut v {
@ -241,7 +268,10 @@ some of the columns in the row contain integers, some floating-point numbers,
and some strings. We can define an enum whose variants will hold the different
value types, and then all the enum variants will be considered the same type:
that of the enum. Then we can create a vector that holds that enum and so,
ultimately, holds different types. Weve demonstrated this in Listing 8-10.
ultimately, holds different types. Weve demonstrated this in [Listing 8-10][Listing-8-10].
[Listing-8-10]: #Listing-8-10
<a name="Listing-8-10"></a>
```rust
enum SpreadsheetCell {
@ -278,3 +308,14 @@ to review the API documentation for all the many useful methods defined on
`Vec<T>` by the standard library. For example, in addition to `push`, a `pop`
method removes and returns the last element. Lets move on to the next
collection type: `String`!
[Listing-8-1]: ch08-01-vectors.html#Listing-8-1
[Listing-8-2]: ch08-01-vectors.html#Listing-8-2
[Listing-8-3]: ch08-01-vectors.html#Listing-8-3
[Listing-8-4]: ch08-01-vectors.html#Listing-8-4
[Listing-8-5]: ch08-01-vectors.html#Listing-8-5
[Listing-8-6]: ch08-01-vectors.html#Listing-8-6
[Listing-8-7]: ch08-01-vectors.html#Listing-8-7
[Listing-8-8]: ch08-01-vectors.html#Listing-8-8
[Listing-8-9]: ch08-01-vectors.html#Listing-8-9
[Listing-8-10]: ch08-01-vectors.html#Listing-8-10

View File

@ -44,8 +44,10 @@ API documentation for more about how to use them and when each is appropriate.
### Creating a New String
Many of the same operations available with `Vec<T>` are available with `String`
as well, starting with the `new` function to create a string, shown in Listing
8-11.
as well, starting with the `new` function to create a string, shown in [Listing 8-11][Listing-8-11].
[Listing-8-11]: #Listing-8-11
<a name="Listing-8-11"></a>
```rust
let mut s = String::new();
@ -56,9 +58,12 @@ let mut s = String::new();
This line creates a new empty string called `s`, which we can then load data
into. Often, well have some initial data that we want to start the string
with. For that, we use the `to_string` method, which is available on any type
that implements the `Display` trait, as string literals do. Listing 8-12 shows
that implements the `Display` trait, as string literals do. [Listing 8-12][Listing-8-12] shows
two examples.
[Listing-8-12]: #Listing-8-12
<a name="Listing-8-12"></a>
```rust
let data = "initial contents";
@ -74,9 +79,12 @@ let s = "initial contents".to_string();
This code creates a string containing `initial contents`.
We can also use the function `String::from` to create a `String` from a string
literal. The code in Listing 8-13 is equivalent to the code from Listing 8-12
literal. The code in [Listing 8-13][Listing-8-13] is equivalent to the code from [Listing 8-12][Listing-8-12]
that uses `to_string`.
[Listing-8-13]: #Listing-8-13
<a name="Listing-8-13"></a>
```rust
let s = String::from("initial contents");
```
@ -90,7 +98,10 @@ redundant, but they all have their place! In this case, `String::from` and
`to_string` do the same thing, so which you choose is a matter of style.
Remember that strings are UTF-8 encoded, so we can include any properly encoded
data in them, as shown in Listing 8-14.
data in them, as shown in [Listing 8-14][Listing-8-14].
[Listing-8-14]: #Listing-8-14
<a name="Listing-8-14"></a>
```rust
let hello = String::from("السلام عليكم");
@ -120,7 +131,10 @@ use the `+` operator or the `format!` macro to concatenate `String` values.
#### Appending to a String with `push_str` and `push`
We can grow a `String` by using the `push_str` method to append a string slice,
as shown in Listing 8-15.
as shown in [Listing 8-15][Listing-8-15].
[Listing-8-15]: #Listing-8-15
<a name="Listing-8-15"></a>
```rust
let mut s = String::from("foo");
@ -132,9 +146,12 @@ using the `push_str` method</span>
After these two lines, `s` will contain `foobar`. The `push_str` method takes a
string slice because we dont necessarily want to take ownership of the
parameter. For example, the code in Listing 8-16 shows that it would be
parameter. For example, the code in [Listing 8-16][Listing-8-16] shows that it would be
unfortunate if we werent able to use `s2` after appending its contents to `s1`.
[Listing-8-16]: #Listing-8-16
<a name="Listing-8-16"></a>
```rust
let mut s1 = String::from("foo");
let s2 = "bar";
@ -149,9 +166,12 @@ If the `push_str` method took ownership of `s2`, we wouldnt be able to print
its value on the last line. However, this code works as wed expect!
The `push` method takes a single character as a parameter and adds it to the
`String`. Listing 8-17 shows code that adds the letter *l* to a `String` using
`String`. [Listing 8-17][Listing-8-17] shows code that adds the letter *l* to a `String` using
the `push` method.
[Listing-8-17]: #Listing-8-17
<a name="Listing-8-17"></a>
```rust
let mut s = String::from("lo");
s.push('l');
@ -165,7 +185,10 @@ As a result of this code, `s` will contain `lol`.
#### Concatenation with the `+` Operator or the `format!` Macro
Often, youll want to combine two existing strings. One way is to use the `+`
operator, as shown in Listing 8-18.
operator, as shown in [Listing 8-18][Listing-8-18].
[Listing-8-18]: #Listing-8-18
<a name="Listing-8-18"></a>
```rust
let s1 = String::from("Hello, ");
@ -197,7 +220,7 @@ First, `s2` has an `&`, meaning that were adding a *reference* of the second
string to the first string because of the `s` parameter in the `add` function:
we can only add a `&str` to a `String`; we cant add two `String` values
together. But wait—the type of `&s2` is `&String`, not `&str`, as specified in
the second parameter to `add`. So why does Listing 8-18 compile?
the second parameter to `add`. So why does [Listing 8-18][Listing-8-18] compile?
The reason were able to use `&s2` in the call to `add` is that the compiler
can *coerce* the `&String` argument into a `&str`. When we call the `add`
@ -207,7 +230,7 @@ not take ownership of the `s` parameter, `s2` will still be a valid `String`
after this operation.
Second, we can see in the signature that `add` takes ownership of `self`,
because `self` does *not* have an `&`. This means `s1` in Listing 8-18 will be
because `self` does *not* have an `&`. This means `s1` in [Listing 8-18][Listing-8-18] will be
moved into the `add` call and no longer be valid after that. So although `let
s3 = s1 + &s2;` looks like it will copy both strings and create a new one, this
statement actually takes ownership of `s1`, appends a copy of the contents of
@ -248,7 +271,10 @@ easier to read and doesnt take ownership of any of its parameters.
In many other programming languages, accessing individual characters in a
string by referencing them by index is a valid and common operation. However,
if you try to access parts of a `String` using indexing syntax in Rust, youll
get an error. Consider the invalid code in Listing 8-19.
get an error. Consider the invalid code in [Listing 8-19][Listing-8-19].
[Listing-8-19]: #Listing-8-19
<a name="Listing-8-19"></a>
```rust,ignore
let s1 = String::from("hello");
@ -277,7 +303,7 @@ memory.
#### Internal Representation
A `String` is a wrapper over a `Vec<u8>`. Lets look at some of our properly
encoded UTF-8 example strings from Listing 8-14. First, this one:
encoded UTF-8 example strings from [Listing 8-14][Listing-8-14]. First, this one:
```rust
let len = String::from("Hola").len();
@ -450,3 +476,13 @@ from having to handle errors involving non-ASCII characters later in your
development life cycle.
Lets switch to something a bit less complex: hash maps!
[Listing-8-11]: ch08-02-strings.html#Listing-8-11
[Listing-8-12]: ch08-02-strings.html#Listing-8-12
[Listing-8-13]: ch08-02-strings.html#Listing-8-13
[Listing-8-14]: ch08-02-strings.html#Listing-8-14
[Listing-8-15]: ch08-02-strings.html#Listing-8-15
[Listing-8-16]: ch08-02-strings.html#Listing-8-16
[Listing-8-17]: ch08-02-strings.html#Listing-8-17
[Listing-8-18]: ch08-02-strings.html#Listing-8-18
[Listing-8-19]: ch08-02-strings.html#Listing-8-19

View File

@ -20,10 +20,13 @@ As always, check the standard library documentation for more information.
### Creating a New Hash Map
You can create an empty hash map with `new` and add elements with `insert`. In
Listing 8-20, were keeping track of the scores of two teams whose names are
[Listing 8-20][Listing-8-20], were keeping track of the scores of two teams whose names are
Blue and Yellow. The Blue team starts with 10 points, and the Yellow team
starts with 50.
[Listing-8-20]: #Listing-8-20
<a name="Listing-8-20"></a>
```rust
use std::collections::HashMap;
@ -53,7 +56,10 @@ vector of tuples, where each tuple consists of a key and its value. The
`HashMap`. For example, if we had the team names and initial scores in two
separate vectors, we could use the `zip` method to create a vector of tuples
where “Blue” is paired with 10, and so forth. Then we could use the `collect`
method to turn that vector of tuples into a hash map, as shown in Listing 8-21.
method to turn that vector of tuples into a hash map, as shown in [Listing 8-21][Listing-8-21].
[Listing-8-21]: #Listing-8-21
<a name="Listing-8-21"></a>
```rust
use std::collections::HashMap;
@ -77,7 +83,10 @@ contains based on the types of the data in the vectors.
For types that implement the `Copy` trait, like `i32`, the values are copied
into the hash map. For owned values like `String`, the values will be moved and
the hash map will be the owner of those values, as demonstrated in Listing 8-22.
the hash map will be the owner of those values, as demonstrated in [Listing 8-22][Listing-8-22].
[Listing-8-22]: #Listing-8-22
<a name="Listing-8-22"></a>
```rust
use std::collections::HashMap;
@ -105,7 +114,10 @@ the “Validating References with Lifetimes” section in Chapter 10.
### Accessing Values in a Hash Map
We can get a value out of the hash map by providing its key to the `get`
method, as shown in Listing 8-23.
method, as shown in [Listing 8-23][Listing-8-23].
[Listing-8-23]: #Listing-8-23
<a name="Listing-8-23"></a>
```rust
use std::collections::HashMap;
@ -166,10 +178,13 @@ of these!
If we insert a key and a value into a hash map and then insert that same key
with a different value, the value associated with that key will be replaced.
Even though the code in Listing 8-24 calls `insert` twice, the hash map will
Even though the code in [Listing 8-24][Listing-8-24] calls `insert` twice, the hash map will
only contain one key/value pair because were inserting the value for the Blue
teams key both times.
[Listing-8-24]: #Listing-8-24
<a name="Listing-8-24"></a>
```rust
use std::collections::HashMap;
@ -196,7 +211,10 @@ that takes the key you want to check as a parameter. The return value of the
might not exist. Lets say we want to check whether the key for the Yellow team
has a value associated with it. If it doesnt, we want to insert the value 50,
and the same for the Blue team. Using the `entry` API, the code looks like
Listing 8-25.
[Listing 8-25][Listing-8-25].
[Listing-8-25]: #Listing-8-25
<a name="Listing-8-25"></a>
```rust
use std::collections::HashMap;
@ -219,7 +237,7 @@ inserts the parameter as the new value for this key and returns a mutable
reference to the new value. This technique is much cleaner than writing the
logic ourselves and, in addition, plays more nicely with the borrow checker.
Running the code in Listing 8-25 will print `{"Yellow": 50, "Blue": 10}`. The
Running the code in [Listing 8-25][Listing-8-25] will print `{"Yellow": 50, "Blue": 10}`. The
first call to `entry` will insert the key for the Yellow team with the value
50 because the Yellow team doesnt have a value already. The second call to
`entry` will not change the hash map because the Blue team already has the
@ -228,12 +246,15 @@ value 10.
#### Updating a Value Based on the Old Value
Another common use case for hash maps is to look up a keys value and then
update it based on the old value. For instance, Listing 8-26 shows code that
update it based on the old value. For instance, [Listing 8-26][Listing-8-26] shows code that
counts how many times each word appears in some text. We use a hash map with
the words as keys and increment the value to keep track of how many times weve
seen that word. If its the first time weve seen a word, well first insert
the value 0.
[Listing-8-26]: #Listing-8-26
<a name="Listing-8-26"></a>
```rust
use std::collections::HashMap;
@ -297,3 +318,11 @@ and hash maps have that will be helpful for these exercises!
Were getting into more complex programs in which operations can fail, so, its
a perfect time to discuss error handling. Well do that next!
[Listing-8-20]: ch08-03-hash-maps.html#Listing-8-20
[Listing-8-21]: ch08-03-hash-maps.html#Listing-8-21
[Listing-8-22]: ch08-03-hash-maps.html#Listing-8-22
[Listing-8-23]: ch08-03-hash-maps.html#Listing-8-23
[Listing-8-24]: ch08-03-hash-maps.html#Listing-8-24
[Listing-8-25]: ch08-03-hash-maps.html#Listing-8-25
[Listing-8-26]: ch08-03-hash-maps.html#Listing-8-26

View File

@ -63,11 +63,14 @@ backtrace is in more detail next.
Lets look at another example to see what its like when a `panic!` call comes
from a library because of a bug in our code instead of from our code calling
the macro directly. Listing 9-1 has some code that attempts to access an
the macro directly. [Listing 9-1][Listing-9-1] has some code that attempts to access an
element by index in a vector.
<span class="filename">Filename: src/main.rs</span>
[Listing-9-1]: #Listing-9-1
<a name="Listing-9-1"></a>
```rust,should_panic
fn main() {
let v = vec![1, 2, 3];
@ -122,7 +125,10 @@ mentioning your files are code that your code called; the lines below are code
that called your code. These lines might include core Rust code, standard
library code, or crates that youre using. Lets try getting a backtrace by
setting the `RUST_BACKTRACE` environment variable to any value except 0.
Listing 9-2 shows output similar to what youll see.
[Listing 9-2][Listing-9-2] shows output similar to what youll see.
[Listing-9-2]: #Listing-9-2
<a name="Listing-9-2"></a>
```text
$ RUST_BACKTRACE=1 cargo run
@ -175,10 +181,10 @@ information, debug symbols must be enabled. Debug symbols are enabled by
default when using `cargo build` or `cargo run` without the `--release` flag,
as we have here.
In the output in Listing 9-2, line 11 of the backtrace points to the line in
In the output in [Listing 9-2][Listing-9-2], line 11 of the backtrace points to the line in
our project thats causing the problem: line 4 of *src/main.rs*. If we dont
want our program to panic, the location pointed to by the first line mentioning
a file we wrote is where we should start investigating. In Listing 9-1, where
a file we wrote is where we should start investigating. In [Listing 9-1][Listing-9-1], where
we deliberately wrote code that would panic in order to demonstrate how to use
backtraces, the way to fix the panic is to not request an element at index 99
from a vector that only contains 3 items. When your code panics in the future,
@ -189,3 +195,6 @@ Well come back to `panic!` and when we should and should not use `panic!` to
handle error conditions in the “To `panic!` or Not to `panic!`” section later
in this chapter. Next, well look at how to recover from an error using
`Result`.
[Listing-9-1]: ch09-01-unrecoverable-errors-with-panic.html#Listing-9-1
[Listing-9-2]: ch09-01-unrecoverable-errors-with-panic.html#Listing-9-2

View File

@ -29,10 +29,13 @@ library has defined on it in many different situations where the successful
value and error value we want to return may differ.
Lets call a function that returns a `Result` value because the function could
fail. In Listing 9-3 we try to open a file.
fail. In [Listing 9-3][Listing-9-3] we try to open a file.
<span class="filename">Filename: src/main.rs</span>
[Listing-9-3]: #Listing-9-3
<a name="Listing-9-3"></a>
```rust
use std::fs::File;
@ -87,13 +90,16 @@ an instance of `Ok` that contains a file handle. In the case where it fails,
the value in `f` will be an instance of `Err` that contains more information
about the kind of error that happened.
We need to add to the code in Listing 9-3 to take different actions depending
on the value `File::open` returns. Listing 9-4 shows one way to handle the
We need to add to the code in [Listing 9-3][Listing-9-3] to take different actions depending
on the value `File::open` returns. [Listing 9-4][Listing-9-4] shows one way to handle the
`Result` using a basic tool, the `match` expression that we discussed in
Chapter 6.
<span class="filename">Filename: src/main.rs</span>
[Listing-9-4]: #Listing-9-4
<a name="Listing-9-4"></a>
```rust,should_panic
use std::fs::File;
@ -135,19 +141,22 @@ As usual, this output tells us exactly what has gone wrong.
### Matching on Different Errors
The code in Listing 9-4 will `panic!` no matter why `File::open` failed. What
The code in [Listing 9-4][Listing-9-4] will `panic!` no matter why `File::open` failed. What
we want to do instead is take different actions for different failure reasons:
if `File::open` failed because the file doesnt exist, we want to create the
file and return the handle to the new file. If `File::open` failed for any
other reason—for example, because we didnt have permission to open the file—we
still want the code to `panic!` in the same way as it did in Listing 9-4. Look
at Listing 9-5, which adds another arm to the `match`.
still want the code to `panic!` in the same way as it did in [Listing 9-4][Listing-9-4]. Look
at [Listing 9-5][Listing-9-5], which adds another arm to the `match`.
<span class="filename">Filename: src/main.rs</span>
<!-- ignore this test because otherwise it creates hello.txt which causes other
tests to fail lol -->
[Listing-9-5]: #Listing-9-5
<a name="Listing-9-5"></a>
```rust,ignore
use std::fs::File;
use std::io::ErrorKind;
@ -213,7 +222,7 @@ Using `match` works well enough, but it can be a bit verbose and doesnt alway
communicate intent well. The `Result<T, E>` type has many helper methods
defined on it to do various tasks. One of those methods, called `unwrap`, is a
shortcut method that is implemented just like the `match` expression we wrote
in Listing 9-4. If the `Result` value is the `Ok` variant, `unwrap` will return
in [Listing 9-4][Listing-9-4]. If the `Result` value is the `Ok` variant, `unwrap` will return
the value inside the `Ok`. If the `Result` is the `Err` variant, `unwrap` will
call the `panic!` macro for us. Here is an example of `unwrap` in action:
@ -276,12 +285,15 @@ error to the calling code so that it can decide what to do. This is known as
might be more information or logic that dictates how the error should be
handled than what you have available in the context of your code.
For example, Listing 9-6 shows a function that reads a username from a file. If
For example, [Listing 9-6][Listing-9-6] shows a function that reads a username from a file. If
the file doesnt exist or cant be read, this function will return those errors
to the code that called this function.
<span class="filename">Filename: src/main.rs</span>
[Listing-9-6]: #Listing-9-6
<a name="Listing-9-6"></a>
```rust
use std::io;
use std::io::Read;
@ -323,7 +335,7 @@ function and the `read_to_string` method.
The body of the function starts by calling the `File::open` function. Then we
handle the `Result` value returned with a `match` similar to the `match` in
Listing 9-4, only instead of calling `panic!` in the `Err` case, we return
[Listing 9-4][Listing-9-4], only instead of calling `panic!` in the `Err` case, we return
early from this function and pass the error value from `File::open` back to the
calling code as this functions error value. If `File::open` succeeds, we store
the file handle in the variable `f` and continue.
@ -353,12 +365,15 @@ question mark operator `?` to make this easier.
#### A Shortcut for Propagating Errors: the `?` Operator
Listing 9-7 shows an implementation of `read_username_from_file` that has the
same functionality as it had in Listing 9-6, but this implementation uses the
[Listing 9-7][Listing-9-7] shows an implementation of `read_username_from_file` that has the
same functionality as it had in [Listing 9-6][Listing-9-6], but this implementation uses the
`?` operator.
<span class="filename">Filename: src/main.rs</span>
[Listing-9-7]: #Listing-9-7
<a name="Listing-9-7"></a>
```rust
use std::io;
use std::io::Read;
@ -376,14 +391,14 @@ fn read_username_from_file() -> Result<String, io::Error> {
calling code using the `?` operator</span>
The `?` placed after a `Result` value is defined to work in almost the same way
as the `match` expressions we defined to handle the `Result` values in Listing
9-6. If the value of the `Result` is an `Ok`, the value inside the `Ok` will
as the `match` expressions we defined to handle the `Result` values in [Listing 9-6][Listing-9-6].
If the value of the `Result` is an `Ok`, the value inside the `Ok` will
get returned from this expression, and the program will continue. If the value
is an `Err`, the value inside the `Err` will be returned from the whole
function as if we had used the `return` keyword so the error value gets
propagated to the calling code.
There is a difference between what the `match` expression from Listing 9-6 and
There is a difference between what the `match` expression from [Listing 9-6][Listing-9-6] and
the `?` operator do: error values used with `?` go through the `from` function,
defined in the `From` trait in the standard library, which is used to convert
errors from one type into another. When the `?` operator calls the `from`
@ -394,7 +409,7 @@ might fail for many different reasons. As long as each error type implements
the `from` function to define how to convert itself to the returned error type,
the `?` operator takes care of the conversion automatically.
In the context of Listing 9-7, the `?` at the end of the `File::open` call will
In the context of [Listing 9-7][Listing-9-7], the `?` at the end of the `File::open` call will
return the value inside an `Ok` to the variable `f`. If an error occurs, the
`?` operator will return early out of the whole function and give any `Err`
value to the calling code. The same thing applies to the `?` at the end of the
@ -402,10 +417,13 @@ value to the calling code. The same thing applies to the `?` at the end of the
The `?` operator eliminates a lot of boilerplate and makes this functions
implementation simpler. We could even shorten this code further by chaining
method calls immediately after the `?`, as shown in Listing 9-8.
method calls immediately after the `?`, as shown in [Listing 9-8][Listing-9-8].
<span class="filename">Filename: src/main.rs</span>
[Listing-9-8]: #Listing-9-8
<a name="Listing-9-8"></a>
```rust
use std::io;
use std::io::Read;
@ -429,14 +447,14 @@ chained the call to `read_to_string` directly onto the result of
`File::open("hello.txt")?`. We still have a `?` at the end of the
`read_to_string` call, and we still return an `Ok` value containing the
username in `s` when both `File::open` and `read_to_string` succeed rather than
returning errors. The functionality is again the same as in Listing 9-6 and
Listing 9-7; this is just a different, more ergonomic way to write it.
returning errors. The functionality is again the same as in [Listing 9-6][Listing-9-6] and
[Listing 9-7][Listing-9-7]; this is just a different, more ergonomic way to write it.
#### The `?` Operator Can Only Be Used in Functions That Return `Result`
The `?` operator can only be used in functions that have a return type of
`Result`, because it is defined to work in the same way as the `match`
expression we defined in Listing 9-6. The part of the `match` that requires a
expression we defined in [Listing 9-6][Listing-9-6]. The part of the `match` that requires a
return type of `Result` is `return Err(e)`, so the return type of the function
must be a `Result` to be compatible with this `return`.
@ -477,3 +495,10 @@ operator to potentially propagate the error to the calling code.
Now that weve discussed the details of calling `panic!` or returning `Result`,
lets return to the topic of how to decide which is appropriate to use in which
cases.
[Listing-9-3]: ch09-02-recoverable-errors-with-result.html#Listing-9-3
[Listing-9-4]: ch09-02-recoverable-errors-with-result.html#Listing-9-4
[Listing-9-5]: ch09-02-recoverable-errors-with-result.html#Listing-9-5
[Listing-9-6]: ch09-02-recoverable-errors-with-result.html#Listing-9-6
[Listing-9-7]: ch09-02-recoverable-errors-with-result.html#Listing-9-7
[Listing-9-8]: ch09-02-recoverable-errors-with-result.html#Listing-9-8

View File

@ -168,10 +168,13 @@ tedious (and might impact performance).
Instead, we can make a new type and put the validations in a function to create
an instance of the type rather than repeating the validations everywhere. That
way, its safe for functions to use the new type in their signatures and
confidently use the values they receive. Listing 9-9 shows one way to define a
confidently use the values they receive. [Listing 9-9][Listing-9-9] shows one way to define a
`Guess` type that will only create an instance of `Guess` if the `new` function
receives a value between 1 and 100.
[Listing-9-9]: #Listing-9-9
<a name="Listing-9-9"></a>
```rust
pub struct Guess {
value: u32,
@ -242,3 +245,5 @@ situations will make your code more reliable in the face of inevitable problems.
Now that youve seen useful ways that the standard library uses generics with
the `Option` and `Result` enums, well talk about how generics work and how you
can use them in your code.
[Listing-9-9]: ch09-03-to-panic-or-not-to-panic.html#Listing-9-9

View File

@ -36,10 +36,13 @@ you recognize duplicated code to extract into a function, youll start to
recognize duplicated code that can use generics.
Consider a short program that finds the largest number in a list, as shown in
Listing 10-1.
[Listing 10-1][Listing-10-1].
<span class="filename">Filename: src/main.rs</span>
[Listing-10-1]: #Listing-10-1
<a name="Listing-10-1"></a>
```rust
fn main() {
let number_list = vec![34, 50, 25, 100, 65];
@ -70,11 +73,14 @@ After considering all the numbers in the list, `largest` should hold the
largest number, which in this case is 100.
To find the largest number in two different lists of numbers, we can duplicate
the code in Listing 10-1 and use the same logic at two different places in the
program, as shown in Listing 10-2.
the code in [Listing 10-1][Listing-10-1] and use the same logic at two different places in the
program, as shown in [Listing 10-2][Listing-10-2].
<span class="filename">Filename: src/main.rs</span>
[Listing-10-2]: #Listing-10-2
<a name="Listing-10-2"></a>
```rust
fn main() {
let number_list = vec![34, 50, 25, 100, 65];
@ -114,13 +120,16 @@ function that operates on any list of integers given to it in a parameter. This
solution makes our code clearer and lets us express the concept of finding the
largest number in a list abstractly.
In Listing 10-3, we extracted the code that finds the largest number into a
function named `largest`. Unlike the code in Listing 10-1, which can find the
In [Listing 10-3][Listing-10-3], we extracted the code that finds the largest number into a
function named `largest`. Unlike the code in [Listing 10-1][Listing-10-1], which can find the
largest number in only one particular list, this program can find the largest
number in two different lists.
<span class="filename">Filename: src/main.rs</span>
[Listing-10-3]: #Listing-10-3
<a name="Listing-10-3"></a>
```rust
fn largest(list: &[i32]) -> i32 {
let mut largest = list[0];
@ -157,8 +166,8 @@ concrete slice of `i32` values that we might pass into the function. As a
result, when we call the function, the code runs on the specific values that we
pass in.
In sum, here are the steps we took to change the code from Listing 10-2 to
Listing 10-3:
In sum, here are the steps we took to change the code from [Listing 10-2][Listing-10-2] to
[Listing 10-3][Listing-10-3]:
1. Identify duplicate code.
2. Extract the duplicate code into the body of the function and specify the
@ -173,3 +182,7 @@ abstract types.
For example, say we had two functions: one that finds the largest item in a
slice of `i32` values and one that finds the largest item in a slice of `char`
values. How would we eliminate that duplication? Lets find out!
[Listing-10-1]: ch10-00-generics.html#Listing-10-1
[Listing-10-2]: ch10-00-generics.html#Listing-10-2
[Listing-10-3]: ch10-00-generics.html#Listing-10-3

View File

@ -12,11 +12,14 @@ signature of the function where we would usually specify the data types of the
parameters and return value. Doing so makes our code more flexible and provides
more functionality to callers of our function while preventing code duplication.
Continuing with our `largest` function, Listing 10-4 shows two functions that
Continuing with our `largest` function, [Listing 10-4][Listing-10-4] shows two functions that
both find the largest value in a slice.
<span class="filename">Filename: src/main.rs</span>
[Listing-10-4]: #Listing-10-4
<a name="Listing-10-4"></a>
```rust
fn largest_i32(list: &[i32]) -> i32 {
let mut largest = list[0];
@ -60,7 +63,7 @@ fn main() {
<span class="caption">Listing 10-4: Two functions that differ only in their
names and the types in their signatures</span>
The `largest_i32` function is the one we extracted in Listing 10-3 that finds
The `largest_i32` function is the one we extracted in [Listing 10-3][Listing-10-3] that finds
the largest `i32` in a slice. The `largest_char` function finds the largest
`char` in a slice. The function bodies have the same code, so lets eliminate
the duplication by introducing a generic type parameter in a single function.
@ -87,13 +90,16 @@ We read this definition as: the function `largest` is generic over some type
`T`. This function has one parameter named `list`, which is a slice of values
of type `T`. The `largest` function will return a value of the same type `T`.
Listing 10-5 shows the combined `largest` function definition using the generic
[Listing 10-5][Listing-10-5] shows the combined `largest` function definition using the generic
data type in its signature. The listing also shows how we can call the function
with either a slice of `i32` values or `char` values. Note that this code wont
compile yet, but well fix it later in this chapter.
<span class="filename">Filename: src/main.rs</span>
[Listing-10-5]: #Listing-10-5
<a name="Listing-10-5"></a>
```rust,ignore
fn largest<T>(list: &[T]) -> T {
let mut largest = list[0];
@ -148,11 +154,14 @@ ways of using generic type parameters.
### In Struct Definitions
We can also define structs to use a generic type parameter in one or more
fields using the `<>` syntax. Listing 10-6 shows how to define a `Point<T>`
fields using the `<>` syntax. [Listing 10-6][Listing-10-6] shows how to define a `Point<T>`
struct to hold `x` and `y` coordinate values of any type.
<span class="filename">Filename: src/main.rs</span>
[Listing-10-6]: #Listing-10-6
<a name="Listing-10-6"></a>
```rust
struct Point<T> {
x: T,
@ -178,10 +187,13 @@ Note that because weve used only one generic type to define `Point<T>`, this
definition says that the `Point<T>` struct is generic over some type `T`, and
the fields `x` and `y` are *both* that same type, whatever that type may be. If
we create an instance of a `Point<T>` that has values of different types, as in
Listing 10-7, our code wont compile.
[Listing 10-7][Listing-10-7], our code wont compile.
<span class="filename">Filename: src/main.rs</span>
[Listing-10-7]: #Listing-10-7
<a name="Listing-10-7"></a>
```rust,ignore
struct Point<T> {
x: T,
@ -215,11 +227,14 @@ floating-point variable
To define a `Point` struct where `x` and `y` are both generics but could have
different types, we can use multiple generic type parameters. For example, in
Listing 10-8, we can change the definition of `Point` to be generic over types
[Listing 10-8][Listing-10-8], we can change the definition of `Point` to be generic over types
`T` and `U` where `x` is of type `T` and `y` is of type `U`.
<span class="filename">Filename: src/main.rs</span>
[Listing-10-8]: #Listing-10-8
<a name="Listing-10-8"></a>
```rust
struct Point<T, U> {
x: T,
@ -276,7 +291,7 @@ The `Result` enum is generic over two types, `T` and `E`, and has two variants:
`E`. This definition makes it convenient to use the `Result` enum anywhere we
have an operation that might succeed (return a value of some type `T`) or fail
(return an error of some type `E`). In fact, this is what we used to open a
file in Listing 9-3, where `T` was filled in with the type `std::fs::File` when
file in [Listing 9-3][Listing-9-3], where `T` was filled in with the type `std::fs::File` when
the file was opened successfully and `E` was filled in with the type
`std::io::Error` when there were problems opening the file.
@ -287,11 +302,14 @@ avoid duplication by using generic types instead.
### In Method Definitions
We can implement methods on structs and enums (as we did in Chapter 5) and use
generic types in their definitions, too. Listing 10-9 shows the `Point<T>`
struct we defined in Listing 10-6 with a method named `x` implemented on it.
generic types in their definitions, too. [Listing 10-9][Listing-10-9] shows the `Point<T>`
struct we defined in [Listing 10-6][Listing-10-6] with a method named `x` implemented on it.
<span class="filename">Filename: src/main.rs</span>
[Listing-10-9]: #Listing-10-9
<a name="Listing-10-9"></a>
```rust
struct Point<T> {
x: T,
@ -324,9 +342,12 @@ generic type after `impl`, Rust can identify that the type in the angle
brackets in `Point` is a generic type rather than a concrete type.
We could, for example, implement methods only on `Point<f32>` instances rather
than on `Point<T>` instances with any generic type. In Listing 10-10 we use the
than on `Point<T>` instances with any generic type. In [Listing 10-10][Listing-10-10] we use the
concrete type `f32`, meaning we dont declare any types after `impl`.
[Listing-10-10]: #Listing-10-10
<a name="Listing-10-10"></a>
```rust
# struct Point<T> {
# x: T,
@ -350,8 +371,8 @@ point is from the point at coordinates (0.0, 0.0) and uses mathematical
operations that are available only for floating point types.
Generic type parameters in a struct definition arent always the same as those
you use in that structs method signatures. For example, Listing 10-11 defines
the method `mixup` on the `Point<T, U>` struct from Listing 10-8. The method
you use in that structs method signatures. For example, [Listing 10-11][Listing-10-11] defines
the method `mixup` on the `Point<T, U>` struct from [Listing 10-8][Listing-10-8]. The method
takes another `Point` as a parameter, which might have different types than the
`self` `Point` were calling `mixup` on. The method creates a new `Point`
instance with the `x` value from the `self` `Point` (of type `T`) and the `y`
@ -359,6 +380,9 @@ value from the passed-in `Point` (of type `W`).
<span class="filename">Filename: src/main.rs</span>
[Listing-10-11]: #Listing-10-11
<a name="Listing-10-11"></a>
```rust
struct Point<T, U> {
x: T,
@ -414,7 +438,7 @@ code into specific code by filling in the concrete types that are used when
compiled.
In this process, the compiler does the opposite of the steps we used to create
the generic function in Listing 10-5: the compiler looks at all the places
the generic function in [Listing 10-5][Listing-10-5]: the compiler looks at all the places
where generic code is called and generates code for the concrete types the
generic code is called with.
@ -460,3 +484,14 @@ instance, we pay no runtime cost for using generics. When the code runs, it
performs just as it would if we had duplicated each definition by hand. The
process of monomorphization makes Rusts generics extremely efficient at
runtime.
[Listing-10-4]: ch10-01-syntax.html#Listing-10-4
[Listing-10-5]: ch10-01-syntax.html#Listing-10-5
[Listing-10-6]: ch10-01-syntax.html#Listing-10-6
[Listing-10-7]: ch10-01-syntax.html#Listing-10-7
[Listing-10-8]: ch10-01-syntax.html#Listing-10-8
[Listing-10-9]: ch10-01-syntax.html#Listing-10-9
[Listing-10-10]: ch10-01-syntax.html#Listing-10-10
[Listing-10-11]: ch10-01-syntax.html#Listing-10-11
[Listing-9-3]: ch09-02-recoverable-errors-with-result.html#Listing-9-3
[Listing-10-3]: ch10-00-generics.html#Listing-10-3

View File

@ -24,11 +24,14 @@ to another tweet.
We want to make a media aggregator library that can display summaries of data
that might be stored in a `NewsArticle` or `Tweet` instance. To do this, we
need a summary from each type, and we need to request that summary by calling a
`summarize` method on an instance. Listing 10-12 shows the definition of a
`summarize` method on an instance. [Listing 10-12][Listing-10-12] shows the definition of a
`Summary` trait that expresses this behavior.
<span class="filename">Filename: src/lib.rs</span>
[Listing-10-12]: #Listing-10-12
<a name="Listing-10-12"></a>
```rust
pub trait Summary {
fn summarize(&self) -> String;
@ -55,7 +58,7 @@ one per line and each line ends in a semicolon.
### Implementing a Trait on a Type
Now that weve defined the desired behavior using the `Summary` trait, we can
implement it on the types in our media aggregator. Listing 10-13 shows an
implement it on the types in our media aggregator. [Listing 10-13][Listing-10-13] shows an
implementation of the `Summary` trait on the `NewsArticle` struct that uses the
headline, the author, and the location to create the return value of
`summarize`. For the `Tweet` struct, we define `summarize` as the username
@ -64,6 +67,9 @@ already limited to 280 characters.
<span class="filename">Filename: src/lib.rs</span>
[Listing-10-13]: #Listing-10-13
<a name="Listing-10-13"></a>
```rust
# pub trait Summary {
# fn summarize(&self) -> String;
@ -126,7 +132,7 @@ This code prints `1 new tweet: horse_ebooks: of course, as you probably already
know, people`.
Note that because we defined the `Summary` trait and the `NewsArticle` and
`Tweet` types in the same *lib.rs* in Listing 10-13, theyre all in the same
`Tweet` types in the same *lib.rs* in [Listing 10-13][Listing-10-13], theyre all in the same
scope. Lets say this *lib.rs* is for a crate weve called `aggregator` and
someone else wants to use our crates functionality to implement the `Summary`
trait on a struct defined within their librarys scope. They would need to
@ -134,7 +140,7 @@ import the trait into their scope first. They would do so by specifying `use
aggregator::Summary;`, which then would enable them to implement `Summary` for
their type. The `Summary` trait would also need to be a public trait for
another crate to implement it, which it is because we put the `pub` keyword
before `trait` in Listing 10-12.
before `trait` in [Listing 10-12][Listing-10-12].
One restriction to note with trait implementations is that we can implement a
trait on a type only if either the trait or the type is local to our crate.
@ -161,12 +167,15 @@ in a trait instead of requiring implementations for all methods on every type.
Then, as we implement the trait on a particular type, we can keep or override
each methods default behavior.
Listing 10-14 shows how to specify a default string for the `summarize` method
[Listing 10-14][Listing-10-14] shows how to specify a default string for the `summarize` method
of the `Summary` trait instead of only defining the method signature, as we did
in Listing 10-12.
in [Listing 10-12][Listing-10-12].
<span class="filename">Filename: src/lib.rs</span>
[Listing-10-14]: #Listing-10-14
<a name="Listing-10-14"></a>
```rust
pub trait Summary {
fn summarize(&self) -> String {
@ -202,7 +211,7 @@ println!("New article available! {}", article.summarize());
This code prints `New article available! (Read more...)`.
Creating a default implementation for `summarize` doesnt require us to change
anything about the implementation of `Summary` on `Tweet` in Listing 10-13. The
anything about the implementation of `Summary` on `Tweet` in [Listing 10-13][Listing-10-13]. The
reason is that the syntax for overriding a default implementation is the same
as the syntax for implementing a trait method that doesnt have a default
implementation.
@ -265,7 +274,7 @@ can explore how to use traits with generic type parameters. We can use *trait
bounds* to constrain generic types to ensure the type will be limited to those
that implement a particular trait and behavior.
For example, in Listing 10-13, we implemented the `Summary` trait on the types
For example, in [Listing 10-13][Listing-10-13], we implemented the `Summary` trait on the types
`NewsArticle` and `Tweet`. We can define a function `notify` that calls the
`summarize` method on its parameter `item`, which is of the generic type `T`.
To be able to call `summarize` on `item` without getting an error telling us
@ -317,7 +326,7 @@ without lots of trait bounds.
### Fixing the `largest` Function with Trait Bounds
Now that you know how to specify the behavior you want to use using the generic
type parameters bounds, lets return to Listing 10-5 to fix the definition of
type parameters bounds, lets return to [Listing 10-5][Listing-10-5] to fix the definition of
the `largest` function that uses a generic type parameter! Last time we tried
to run that code, we received this error:
@ -376,13 +385,16 @@ able to move the value out of `list[0]` and into the `largest` variable,
resulting in this error.
To call this code with only those types that implement the `Copy` trait, we can
add `Copy` to the trait bounds of `T`! Listing 10-15 shows the complete code of
add `Copy` to the trait bounds of `T`! [Listing 10-15][Listing-10-15] shows the complete code of
a generic `largest` function that will compile as long as the types of the
values in the slice that we pass into the function implement the `PartialOrd`
*and* `Copy` traits, like `i32` and `char` do.
<span class="filename">Filename: src/main.rs</span>
[Listing-10-15]: #Listing-10-15
<a name="Listing-10-15"></a>
```rust
fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
let mut largest = list[0];
@ -431,11 +443,14 @@ avoid heap allocations. Try implementing these alternate solutions on your own!
By using a trait bound with an `impl` block that uses generic type parameters,
we can implement methods conditionally for types that implement the specified
traits. For example, the type `Pair<T>` in Listing 10-16 always implements the
traits. For example, the type `Pair<T>` in [Listing 10-16][Listing-10-16] always implements the
`new` function. But `Pair<T>` only implements the `cmp_display` method if its
inner type `T` implements the `PartialOrd` trait that enables comparison *and*
the `Display` trait that enables printing.
[Listing-10-16]: #Listing-10-16
<a name="Listing-10-16"></a>
```rust
use std::fmt::Display;
@ -508,3 +523,10 @@ Another kind of generic that weve already been using is called *lifetimes*.
Rather than ensuring that a type has the behavior we want, lifetimes ensure
that references are valid as long as we need them to be. Lets look at how
lifetimes do that.
[Listing-10-12]: ch10-02-traits.html#Listing-10-12
[Listing-10-13]: ch10-02-traits.html#Listing-10-13
[Listing-10-14]: ch10-02-traits.html#Listing-10-14
[Listing-10-15]: ch10-02-traits.html#Listing-10-15
[Listing-10-16]: ch10-02-traits.html#Listing-10-16
[Listing-10-5]: ch10-01-syntax.html#Listing-10-5

View File

@ -20,9 +20,12 @@ detailed information.
The main aim of lifetimes is to prevent dangling references, which cause a
program to reference data other than the data its intended to reference.
Consider the program in Listing 10-17, which has an outer scope and an inner
Consider the program in [Listing 10-17][Listing-10-17], which has an outer scope and an inner
scope.
[Listing-10-17]: #Listing-10-17
<a name="Listing-10-17"></a>
```rust,ignore
{
let r;
@ -77,8 +80,11 @@ It uses a borrow checker.
### The Borrow Checker
The Rust compiler has a *borrow checker* that compares scopes to determine
whether all borrows are valid. Listing 10-18 shows the same code as Listing
10-17 but with annotations showing the lifetimes of the variables.
whether all borrows are valid. [Listing 10-18][Listing-10-18] shows the same code as [Listing 10-17][Listing-10-17]
but with annotations showing the lifetimes of the variables.
[Listing-10-18]: #Listing-10-18
<a name="Listing-10-18"></a>
```rust,ignore
{
@ -103,9 +109,12 @@ lifetimes and sees that `r` has a lifetime of `'a` but that it refers to memory
with a lifetime of `'b`. The program is rejected because `'b` is shorter than
`'a`: the subject of the reference doesnt live as long as the reference.
Listing 10-19 fixes the code so it doesnt have a dangling reference and
[Listing 10-19][Listing-10-19] fixes the code so it doesnt have a dangling reference and
compiles without any errors.
[Listing-10-19]: #Listing-10-19
<a name="Listing-10-19"></a>
```rust
{
let x = 5; // ----------+-- 'b
@ -132,11 +141,14 @@ lifetimes of parameters and return values in the context of functions.
Lets write a function that returns the longer of two string slices. This
function will take two string slices and return a string slice. After weve
implemented the `longest` function, the code in Listing 10-20 should print `The
implemented the `longest` function, the code in [Listing 10-20][Listing-10-20] should print `The
longest string is abcd`.
<span class="filename">Filename: src/main.rs</span>
[Listing-10-20]: #Listing-10-20
<a name="Listing-10-20"></a>
```rust,ignore
fn main() {
let string1 = String::from("abcd");
@ -157,14 +169,17 @@ type stored in the variable `string1`) as well as string literals (which is
what variable `string2` contains).
Refer to the “String Slices as Parameters” section in Chapter 4 for more
discussion about why the parameters we use in Listing 10-20 are the ones we
discussion about why the parameters we use in [Listing 10-20][Listing-10-20] are the ones we
want.
If we try to implement the `longest` function as shown in Listing 10-21, it
If we try to implement the `longest` function as shown in [Listing 10-21][Listing-10-21], it
wont compile.
<span class="filename">Filename: src/main.rs</span>
[Listing-10-21]: #Listing-10-21
<a name="Listing-10-21"></a>
```rust,ignore
fn longest(x: &str, y: &str) -> &str {
if x.len() > y.len() {
@ -251,10 +266,13 @@ parameters inside angle brackets between the function name and the parameter
list. The constraint we want to express in this signature is that all the
references in the parameters and the return value must have the same lifetime.
Well name the lifetime `'a` and then add it to each reference, as shown in
Listing 10-22.
[Listing 10-22][Listing-10-22].
<span class="filename">Filename: src/main.rs</span>
[Listing-10-22]: #Listing-10-22
<a name="Listing-10-22"></a>
```rust
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
@ -270,7 +288,7 @@ specifying that all the references in the signature must have the same lifetime
`'a`</span>
This code should compile and produce the result we want when we use it with the
`main` function in Listing 10-20.
`main` function in [Listing 10-20][Listing-10-20].
The function signature now tells Rust that for some lifetime `'a`, the function
takes two parameters, both of which are string slices that live at least as
@ -301,11 +319,14 @@ the returned reference will also be valid for the length of the smaller of the
lifetimes of `x` and `y`.
Lets look at how the lifetime annotations restrict the `longest` function by
passing in references that have different concrete lifetimes. Listing 10-23 is
passing in references that have different concrete lifetimes. [Listing 10-23][Listing-10-23] is
a straightforward example.
<span class="filename">Filename: src/main.rs</span>
[Listing-10-23]: #Listing-10-23
<a name="Listing-10-23"></a>
```rust
# fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
# if x.len() > y.len() {
@ -340,11 +361,14 @@ Next, lets try an example that shows that the lifetime of the reference in
declaration of the `result` variable outside the inner scope but leave the
assignment of the value to the `result` variable inside the scope with
`string2`. Then well move the `println!` that uses `result` outside the inner
scope, after the inner scope has ended. The code in Listing 10-24 will not
scope, after the inner scope has ended. The code in [Listing 10-24][Listing-10-24] will not
compile.
<span class="filename">Filename: src/main.rs</span>
[Listing-10-24]: #Listing-10-24
<a name="Listing-10-24"></a>
```rust,ignore
fn main() {
let string1 = String::from("long string is long");
@ -387,7 +411,7 @@ still be valid for the `println!` statement. However, the compiler cant see
that the reference is valid in this case. Weve told Rust that the lifetime of
the reference returned by the `longest` function is the same as the smaller of
the lifetimes of the references passed in. Therefore, the borrow checker
disallows the code in Listing 10-24 as possibly having an invalid reference.
disallows the code in [Listing 10-24][Listing-10-24] as possibly having an invalid reference.
Try designing more experiments that vary the values and lifetimes of the
references passed in to the `longest` function and how the returned reference
@ -472,11 +496,14 @@ would create dangling pointers or otherwise violate memory safety.
So far, weve only defined structs to hold owned types. Its possible for
structs to hold references, but in that case we would need to add a lifetime
annotation on every reference in the structs definition. Listing 10-25 has a
annotation on every reference in the structs definition. [Listing 10-25][Listing-10-25] has a
struct named `ImportantExcerpt` that holds a string slice.
<span class="filename">Filename: src/main.rs</span>
[Listing-10-25]: #Listing-10-25
<a name="Listing-10-25"></a>
```rust
struct ImportantExcerpt<'a> {
part: &'a str,
@ -512,11 +539,14 @@ the `ImportantExcerpt` goes out of scope, so the reference in the
Youve learned that every reference has a lifetime and that you need to specify
lifetime parameters for functions or structs that use references. However, in
Chapter 4 we had a function in Listing 4-9, which is shown again in Listing
10-26, that compiled without lifetime annotations.
Chapter 4 we had a function in [Listing 4-9][Listing-4-9], which is shown again in [Listing 10-26][Listing-10-26],
that compiled without lifetime annotations.
<span class="filename">Filename: src/lib.rs</span>
[Listing-10-26]: #Listing-10-26
<a name="Listing-10-26"></a>
```rust
fn first_word(s: &str) -> &str {
let bytes = s.as_bytes();
@ -531,7 +561,7 @@ fn first_word(s: &str) -> &str {
}
```
<span class="caption">Listing 10-26: A function we defined in Listing 4-9 that
<span class="caption">Listing 10-26: A function we defined in [Listing 4-9][Listing-4-9] that
compiled without lifetime annotations, even though the parameter and return
type are references</span>
@ -593,7 +623,7 @@ much nicer to read and write because fewer symbols are necessary.
Lets pretend were the compiler. Well apply these rules to figure out what
the lifetimes of the references in the signature of the `first_word` function
in Listing 10-26 are. The signature starts without any lifetimes associated
in [Listing 10-26][Listing-10-26] are. The signature starts without any lifetimes associated
with the references:
```rust,ignore
@ -621,7 +651,7 @@ compiler can continue its analysis without needing the programmer to annotate
the lifetimes in this function signature.
Lets look at another example, this time using the `longest` function that had
no lifetime parameters when we started working with it in Listing 10-21:
no lifetime parameters when we started working with it in [Listing 10-21][Listing-10-21]:
```rust,ignore
fn longest(x: &str, y: &str) -> &str {
@ -639,7 +669,7 @@ input lifetime. The third rule doesnt apply either, because `longest` is a
function rather than a method, so none of the parameters are `self`. After
working through all three rules, we still havent figured out what the return
types lifetime is. This is why we got an error trying to compile the code in
Listing 10-21: the compiler worked through the lifetime elision rules but still
[Listing 10-21][Listing-10-21]: the compiler worked through the lifetime elision rules but still
couldnt figure out all the lifetimes of the references in the signature.
Because the third rule really only applies in method signatures, well look at
@ -649,7 +679,7 @@ annotate lifetimes in method signatures very often.
### Lifetime Annotations in Method Definitions
When we implement methods on a struct with lifetimes, we use the same syntax as
that of generic type parameters shown in Listing 10-11. Where we declare and
that of generic type parameters shown in [Listing 10-11][Listing-10-11]. Where we declare and
use the lifetime parameters depends on whether theyre related to the struct
fields or the method parameters and return values.
@ -661,7 +691,7 @@ In method signatures inside the `impl` block, references might be tied to the
lifetime of references in the structs fields, or they might be independent. In
addition, the lifetime elision rules often make it so that lifetime annotations
arent necessary in method signatures. Lets look at some examples using the
struct named `ImportantExcerpt` that we defined in Listing 10-25.
struct named `ImportantExcerpt` that we defined in [Listing 10-25][Listing-10-25].
First, well use a method named `level` whose only parameter is a reference to
`self` and whose return value is an `i32`, which is not a reference to anything:
@ -744,7 +774,7 @@ fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a st
}
```
This is the `longest` function from Listing 10-22 that returns the longer of
This is the `longest` function from [Listing 10-22][Listing-10-22] that returns the longer of
two string slices. But now it has an extra parameter named `ann` of the generic
type `T`, which can be filled in by any type that implements the `Display`
trait as specified by the `where` clause. This extra parameter will be printed
@ -769,3 +799,16 @@ this chapter: Chapter 17 discusses trait objects, which are another way to use
traits. Chapter 19 covers more complex scenarios involving lifetime annotations
as well as some advanced type system features. But next, youll learn how to
write tests in Rust so you can make sure your code is working the way it should.
[Listing-10-17]: ch10-03-lifetime-syntax.html#Listing-10-17
[Listing-10-18]: ch10-03-lifetime-syntax.html#Listing-10-18
[Listing-10-19]: ch10-03-lifetime-syntax.html#Listing-10-19
[Listing-10-20]: ch10-03-lifetime-syntax.html#Listing-10-20
[Listing-10-21]: ch10-03-lifetime-syntax.html#Listing-10-21
[Listing-10-22]: ch10-03-lifetime-syntax.html#Listing-10-22
[Listing-10-23]: ch10-03-lifetime-syntax.html#Listing-10-23
[Listing-10-24]: ch10-03-lifetime-syntax.html#Listing-10-24
[Listing-10-25]: ch10-03-lifetime-syntax.html#Listing-10-25
[Listing-10-26]: ch10-03-lifetime-syntax.html#Listing-10-26
[Listing-4-9]: ch04-03-slices.html#Listing-4-9
[Listing-10-11]: ch10-01-syntax.html#Listing-10-11

View File

@ -43,10 +43,13 @@ $ cd adder
```
The contents of the *src/lib.rs* file in your `adder` library should look like
Listing 11-1.
[Listing 11-1][Listing-11-1].
<span class="filename">Filename: src/lib.rs</span>
[Listing-11-1]: #Listing-11-1
<a name="Listing-11-1"></a>
```rust
# fn main() {}
#[cfg(test)]
@ -72,8 +75,10 @@ The function body uses the `assert_eq!` macro to assert that 2 + 2 equals 4.
This assertion serves as an example of the format for a typical test. Lets run
it to see that this test passes.
The `cargo test` command runs all tests in our project, as shown in Listing
11-2.
The `cargo test` command runs all tests in our project, as shown in [Listing 11-2][Listing-11-2].
[Listing-11-2]: #Listing-11-2
<a name="Listing-11-2"></a>
```text
$ cargo test
@ -153,10 +158,13 @@ when something in the test function panics. Each test is run in a new thread,
and when the main thread sees that a test thread has died, the test is marked
as failed. We talked about the simplest way to cause a panic in Chapter 9,
which is to call the `panic!` macro. Enter the new test, `another`, so your
*src/lib.rs* file looks like Listing 11-3.
*src/lib.rs* file looks like [Listing 11-3][Listing-11-3].
<span class="filename">Filename: src/lib.rs</span>
[Listing-11-3]: #Listing-11-3
<a name="Listing-11-3"></a>
```rust
# fn main() {}
#[cfg(test)]
@ -176,8 +184,11 @@ mod tests {
<span class="caption">Listing 11-3: Adding a second test that will fail because
we call the `panic!` macro</span>
Run the tests again using `cargo test`. The output should look like Listing
11-4, which shows that our `exploration` test passed and `another` failed.
Run the tests again using `cargo test`. The output should look like [Listing 11-4][Listing-11-4],
which shows that our `exploration` test passed and `another` failed.
[Listing-11-4]: #Listing-11-4
<a name="Listing-11-4"></a>
```text
running 2 tests
@ -227,12 +238,15 @@ the `assert!` macro calls the `panic!` macro, which causes the test to fail.
Using the `assert!` macro helps us check that our code is functioning in the
way we intend.
In Chapter 5, Listing 5-15, we used a `Rectangle` struct and a `can_hold`
method, which are repeated here in Listing 11-5. Lets put this code in the
In Chapter 5, [Listing 5-15][Listing-5-15], we used a `Rectangle` struct and a `can_hold`
method, which are repeated here in [Listing 11-5][Listing-11-5]. Lets put this code in the
*src/lib.rs* file and write some tests for it using the `assert!` macro.
<span class="filename">Filename: src/lib.rs</span>
[Listing-11-5]: #Listing-11-5
<a name="Listing-11-5"></a>
```rust
# fn main() {}
#[derive(Debug)]
@ -252,13 +266,16 @@ impl Rectangle {
`can_hold` method from Chapter 5</span>
The `can_hold` method returns a Boolean, which means its a perfect use case
for the `assert!` macro. In Listing 11-6, we write a test that exercises the
`can_hold` method by creating a `Rectangle` instance that has a width of 8 and
a height of 7 and asserting that it can hold another `Rectangle` instance that
has a width of 5 and a height of 1.
for the `assert!` macro. In [Listing 11-6][Listing-11-6], we write a test that exercises the
`can_hold` method by creating a `Rectangle` instance that has a length of 8 and
a width of 7 and asserting that it can hold another `Rectangle` instance that
has a length of 5 and a width of 1.
<span class="filename">Filename: src/lib.rs</span>
[Listing-11-6]: #Listing-11-6
<a name="Listing-11-6"></a>
```rust
# fn main() {}
#[cfg(test)]
@ -393,12 +410,15 @@ fails, which makes it easier to see *why* the test failed; conversely, the
`assert!` macro only indicates that it got a `false` value for the `==`
expression, not the values that lead to the `false` value.
In Listing 11-7, we write a function named `add_two` that adds `2` to its
In [Listing 11-7][Listing-11-7], we write a function named `add_two` that adds `2` to its
parameter and returns the result. Then we test this function using the
`assert_eq!` macro.
<span class="filename">Filename: src/lib.rs</span>
[Listing-11-7]: #Listing-11-7
<a name="Listing-11-7"></a>
```rust
# fn main() {}
pub fn add_two(a: i32) -> i32 {
@ -494,7 +514,7 @@ of the standard library types implement these traits. For structs and enums
that you define, youll need to implement `PartialEq` to assert that values of
those types are equal or not equal. Youll need to implement `Debug` to print
the values when the assertion fails. Because both traits are derivable traits,
as mentioned in Listing 5-12 in Chapter 5, this is usually as straightforward
as mentioned in [Listing 5-12][Listing-5-12] in Chapter 5, this is usually as straightforward
as adding the `#[derive(PartialEq, Debug)]` annotation to your struct or enum
definition. See Appendix C for more details about these and other derivable
traits.
@ -602,7 +622,7 @@ debug what happened instead of what we were expecting to happen.
In addition to checking that our code returns the correct values we expect,
its also important to check that our code handles error conditions as we
expect. For example, consider the `Guess` type that we created in Chapter 9,
Listing 9-9. Other code that uses `Guess` depends on the guarantee that `Guess`
[Listing 9-9][Listing-9-9]. Other code that uses `Guess` depends on the guarantee that `Guess`
instances will contain only values between 1 and 100. We can write a test that
ensures that attempting to create a `Guess` instance with a value outside that
range panics.
@ -611,11 +631,14 @@ We do this by adding another attribute, `should_panic`, to our test function.
This attribute makes a test pass if the code inside the function panics; the
test will fail if the code inside the function doesnt panic.
Listing 11-8 shows a test that checks that the error conditions of `Guess::new`
[Listing 11-8][Listing-11-8] shows a test that checks that the error conditions of `Guess::new`
happen when we expect them to.
<span class="filename">Filename: src/lib.rs</span>
[Listing-11-8]: #Listing-11-8
<a name="Listing-11-8"></a>
```rust
# fn main() {}
pub struct Guess {
@ -684,7 +707,7 @@ impl Guess {
}
```
When we run the test in Listing 11-8, it will fail:
When we run the test in [Listing 11-8][Listing-11-8], it will fail:
```text
running 1 test
@ -708,11 +731,14 @@ test panics for a different reason than the one we were expecting to happen. To
make `should_panic` tests more precise, we can add an optional `expected`
parameter to the `should_panic` attribute. The test harness will make sure that
the failure message contains the provided text. For example, consider the
modified code for `Guess` in Listing 11-9 where the `new` function panics with
modified code for `Guess` in [Listing 11-9][Listing-11-9] where the `new` function panics with
different messages depending on whether the value is too small or too large.
<span class="filename">Filename: src/lib.rs</span>
[Listing-11-9]: #Listing-11-9
<a name="Listing-11-9"></a>
```rust
# fn main() {}
# pub struct Guess {
@ -804,3 +830,16 @@ figuring out where our bug is!
Now that you know several ways to write tests, lets look at what is happening
when we run our tests and explore the different options we can use with `cargo
test`.
[Listing-5-12]: ch05-02-example-structs.html#Listing-5-12
[Listing-5-15]: ch05-03-method-syntax.html#Listing-5-15
[Listing-11-1]: ch11-01-writing-tests.html#Listing-11-1
[Listing-11-2]: ch11-01-writing-tests.html#Listing-11-2
[Listing-11-3]: ch11-01-writing-tests.html#Listing-11-3
[Listing-11-4]: ch11-01-writing-tests.html#Listing-11-4
[Listing-11-5]: ch11-01-writing-tests.html#Listing-11-5
[Listing-11-6]: ch11-01-writing-tests.html#Listing-11-6
[Listing-11-7]: ch11-01-writing-tests.html#Listing-11-7
[Listing-11-8]: ch11-01-writing-tests.html#Listing-11-8
[Listing-11-9]: ch11-01-writing-tests.html#Listing-11-9
[Listing-9-9]: ch09-03-to-panic-or-not-to-panic.html#Listing-9-9

View File

@ -56,11 +56,14 @@ passes, we wont see the `println!` output in the terminal; well see only t
line that indicates the test passed. If a test fails, well see whatever was
printed to standard output with the rest of the failure message.
As an example, Listing 11-10 has a silly function that prints the value of its
As an example, [Listing 11-10][Listing-11-10] has a silly function that prints the value of its
parameter and returns 10, as well as a test that passes and a test that fails.
<span class="filename">Filename: src/lib.rs</span>
[Listing-11-10]: #Listing-11-10
<a name="Listing-11-10"></a>
```rust
fn prints_and_returns_10(a: i32) -> i32 {
println!("I got the value {}", a);
@ -122,7 +125,7 @@ output capture behavior by using the `--nocapture` flag:
$ cargo test -- --nocapture
```
When we run the tests in Listing 11-10 again with the `--nocapture` flag, we
When we run the tests in [Listing 11-10][Listing-11-10] again with the `--nocapture` flag, we
see the following output:
```text
@ -157,10 +160,13 @@ that code. You can choose which tests to run by passing `cargo test` the name
or names of the test(s) you want to run as an argument.
To demonstrate how to run a subset of tests, well create three tests for our
`add_two` function, as shown in Listing 11-11, and choose which ones to run.
`add_two` function, as shown in [Listing 11-11][Listing-11-11], and choose which ones to run.
<span class="filename">Filename: src/lib.rs</span>
[Listing-11-11]: #Listing-11-11
<a name="Listing-11-11"></a>
```rust
pub fn add_two(a: i32) -> i32 {
a + 2
@ -304,3 +310,6 @@ By controlling which tests run, you can make sure your `cargo test` results
will be fast. When youre at a point where it makes sense to check the results
of the `ignored` tests and you have time to wait for the results, you can run
`cargo test -- --ignored` instead.
[Listing-11-10]: ch11-02-running-tests.html#Listing-11-10
[Listing-11-11]: ch11-02-running-tests.html#Listing-11-11

View File

@ -62,10 +62,13 @@ Theres debate within the testing community about whether or not private
functions should be tested directly, and other languages make it difficult or
impossible to test private functions. Regardless of which testing ideology you
adhere to, Rusts privacy rules do allow you to test private functions.
Consider the code in Listing 11-12 with the private function `internal_adder`.
Consider the code in [Listing 11-12][Listing-11-12] with the private function `internal_adder`.
<span class="filename">Filename: src/lib.rs</span>
[Listing-11-12]: #Listing-11-12
<a name="Listing-11-12"></a>
```rust
pub fn add_two(a: i32) -> i32 {
internal_adder(a, 2)
@ -111,12 +114,15 @@ to *src*. Cargo knows to look for integration test files in this directory. We
can then make as many test files as we want to in this directory, and Cargo
will compile each of the files as an individual crate.
Lets create an integration test. With the code in Listing 11-12 still in the
Lets create an integration test. With the code in [Listing 11-12][Listing-11-12] still in the
*src/lib.rs* file, make a *tests* directory, create a new file named
*tests/integration_test.rs*, and enter the code in Listing 11-13.
*tests/integration_test.rs*, and enter the code in [Listing 11-13][Listing-11-13].
<span class="filename">Filename: tests/integration_test.rs</span>
[Listing-11-13]: #Listing-11-13
<a name="Listing-11-13"></a>
```rust,ignore
extern crate adder;
@ -165,7 +171,7 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
The three sections of output include the unit tests, the integration test, and
the doc tests. The first section for the unit tests is the same as weve been
seeing: one line for each unit test (one named `internal` that we added in
Listing 11-12) and then a summary line for the unit tests.
[Listing 11-12][Listing-11-12]) and then a summary line for the unit tests.
The integration tests section starts with the line `Running
target/debug/deps/integration_test-ce99bcc2479f4607` (the hash at the end of
@ -290,7 +296,7 @@ fn it_adds_two() {
```
Note that the `mod common;` declaration is the same as the module declarations
we demonstrated in Listing 7-4. Then in the test function, we can call the
we demonstrated in [Listing 7-4][Listing-7-4]. Then in the test function, we can call the
`common::setup()` function.
#### Integration Tests for Binary Crates
@ -322,3 +328,7 @@ reduce logic bugs having to do with how your code is expected to behave.
Lets combine the knowledge you learned in this chapter and in previous
chapters to work on a project!
[Listing-7-4]: ch07-01-mod-and-the-filesystem.html#Listing-7-4
[Listing-11-12]: ch11-03-test-organization.html#Listing-11-12
[Listing-11-13]: ch11-03-test-organization.html#Listing-11-13

View File

@ -35,11 +35,14 @@ details about iterators: iterators produce a series of values, and we can call
the `collect` method on an iterator to turn it into a collection, such as a
vector, containing all the elements the iterator produces.
Use the code in Listing 12-1 to allow your `minigrep` program to read any
Use the code in [Listing 12-1][Listing-12-1] to allow your `minigrep` program to read any
command line arguments passed to it and then collect the values into a vector.
<span class="filename">Filename: src/main.rs</span>
[Listing-12-1]: #Listing-12-1
<a name="Listing-12-1"></a>
```rust
use std::env;
@ -105,10 +108,13 @@ chapter, well ignore it and save only the two arguments we need.
Printing the value of the vector of arguments illustrated that the program is
able to access the values specified as command line arguments. Now we need to
save the values of the two arguments in variables so we can use the values
throughout the rest of the program. We do that in Listing 12-2.
throughout the rest of the program. We do that in [Listing 12-2][Listing-12-2].
<span class="filename">Filename: src/main.rs</span>
[Listing-12-2]: #Listing-12-2
<a name="Listing-12-2"></a>
```rust,should_panic
use std::env;
@ -151,3 +157,6 @@ saved into the right variables. Later well add some error handling to deal
with certain potential erroneous situations, such as when the user provides no
arguments; for now, well ignore that situation and work on adding file-reading
capabilities instead.
[Listing-12-1]: ch12-01-accepting-command-line-arguments.html#Listing-12-1
[Listing-12-2]: ch12-01-accepting-command-line-arguments.html#Listing-12-2

View File

@ -3,13 +3,16 @@
Now well add functionality to read the file that is specified in the
`filename` command line argument. First, we need a sample file to test it with:
the best kind of file to use to make sure `minigrep` is working is one with a
small amount of text over multiple lines with some repeated words. Listing 12-3
small amount of text over multiple lines with some repeated words. [Listing 12-3][Listing-12-3]
has an Emily Dickinson poem that will work well! Create a file called
*poem.txt* at the root level of your project, and enter the poem “Im Nobody!
Who are you?”
<span class="filename">Filename: poem.txt</span>
[Listing-12-3]: #Listing-12-3
<a name="Listing-12-3"></a>
```text
I'm nobody! Who are you?
Are you nobody, too?
@ -26,10 +29,13 @@ To an admiring bog!
case</span>
With the text in place, edit *src/main.rs* and add code to open the file, as
shown in Listing 12-4.
shown in [Listing 12-4][Listing-12-4].
<span class="filename">Filename: src/main.rs</span>
[Listing-12-4]: #Listing-12-4
<a name="Listing-12-4"></a>
```rust,should_panic
use std::env;
use std::fs::File;
@ -109,3 +115,6 @@ as we could. The program is still small, so these flaws arent a big problem,
but as the program grows, it will be harder to fix them cleanly. Its good
practice to begin refactoring early on when developing a program, because its
much easier to refactor smaller amounts of code. Well do that next.
[Listing-12-3]: ch12-02-reading-a-file.html#Listing-12-3
[Listing-12-4]: ch12-02-reading-a-file.html#Listing-12-4

View File

@ -69,11 +69,14 @@ reading it. Lets rework our program by following this process.
Well extract the functionality for parsing arguments into a function that
`main` will call to prepare for moving the command line parsing logic to
*src/lib.rs*. Listing 12-5 shows the new start of `main` that calls a new
*src/lib.rs*. [Listing 12-5][Listing-12-5] shows the new start of `main` that calls a new
function `parse_config`, which well define in *src/main.rs* for the moment.
<span class="filename">Filename: src/main.rs</span>
[Listing-12-5]: #Listing-12-5
<a name="Listing-12-5"></a>
```rust,ignore
fn main() {
let args: Vec<String> = env::args().collect();
@ -128,10 +131,13 @@ other and what their purpose is.
> Note: Some people call this anti-pattern of using primitive values when a
> complex type would be more appropriate *primitive obsession*.
Listing 12-6 shows the improvements to the `parse_config` function.
[Listing 12-6][Listing-12-6] shows the improvements to the `parse_config` function.
<span class="filename">Filename: src/main.rs</span>
[Listing-12-6]: #Listing-12-6
<a name="Listing-12-6"></a>
```rust,should_panic
# use std::env;
# use std::fs::File;
@ -220,11 +226,14 @@ named `new` that is associated with the `Config` struct. Making this change
will make the code more idiomatic. We can create instances of types in the
standard library, such as `String`, by calling `String::new`. Similarly, by
changing `parse_config` into a `new` function associated with `Config`, well
be able to create instances of `Config` by calling `Config::new`. Listing 12-7
be able to create instances of `Config` by calling `Config::new`. [Listing 12-7][Listing-12-7]
shows the changes we need to make.
<span class="filename">Filename: src/main.rs</span>
[Listing-12-7]: #Listing-12-7
<a name="Listing-12-7"></a>
```rust,should_panic
# use std::env;
#
@ -284,13 +293,16 @@ happened and what they should do instead. Lets fix that now.
#### Improving the Error Message
In Listing 12-8, we add a check in the `new` function that will verify that the
In [Listing 12-8][Listing-12-8], we add a check in the `new` function that will verify that the
slice is long enough before accessing index 1 and 2. If the slice isnt long
enough, the program panics and displays a better error message than the `index
out of bounds` message.
<span class="filename">Filename: src/main.rs</span>
[Listing-12-8]: #Listing-12-8
<a name="Listing-12-8"></a>
```rust,ignore
// --snip--
fn new(args: &[String]) -> Config {
@ -303,7 +315,7 @@ fn new(args: &[String]) -> Config {
<span class="caption">Listing 12-8: Adding a check for the number of
arguments</span>
This code is similar to the `Guess::new` function we wrote in Listing 9-9,
This code is similar to the `Guess::new` function we wrote in [Listing 9-9][Listing-9-9],
where we called `panic!` when the `value` argument was out of the range of
valid values. Instead of checking for a range of values here, were checking
that the length of `args` is at least 3 and the rest of the function can
@ -325,7 +337,7 @@ note: Run with `RUST_BACKTRACE=1` for a backtrace.
This output is better: we now have a reasonable error message. However, we also
have extraneous information we dont want to give to our users. Perhaps using
the technique we used in Listing 9-9 isnt the best to use here: a call to
the technique we used in [Listing 9-9][Listing-9-9] isnt the best to use here: a call to
`panic!` is more appropriate for a programming problem than a usage problem, as
discussed in Chapter 9. Instead, we can use the other technique you learned
about in Chapter 9—returning a `Result` that indicates either success or an
@ -340,13 +352,16 @@ signal there was a problem. Then we can change `main` to convert an `Err`
variant into a more practical error for our users without the surrounding text
about `thread 'main'` and `RUST_BACKTRACE` that a call to `panic!` causes.
Listing 12-9 shows the changes we need to make to the return value of
[Listing 12-9][Listing-12-9] shows the changes we need to make to the return value of
`Config::new` and the body of the function needed to return a `Result`. Note
that this wont compile until we update `main` as well, which well do in the
next listing.
<span class="filename">Filename: src/main.rs</span>
[Listing-12-9]: #Listing-12-9
<a name="Listing-12-9"></a>
```rust,ignore
impl Config {
fn new(args: &[String]) -> Result<Config, &'static str> {
@ -383,13 +398,16 @@ more cleanly in the error case.
To handle the error case and print a user-friendly message, we need to update
`main` to handle the `Result` being returned by `Config::new`, as shown in
Listing 12-10. Well also take the responsibility of exiting the command line
[Listing 12-10][Listing-12-10]. Well also take the responsibility of exiting the command line
tool with a nonzero error code from `panic!` and implement it by hand. A
nonzero exit status is a convention to signal to the process that called our
program that the program exited with an error state.
<span class="filename">Filename: src/main.rs</span>
[Listing-12-10]: #Listing-12-10
<a name="Listing-12-10"></a>
```rust,ignore
use std::process;
@ -416,7 +434,7 @@ is an `Err` value, this method calls the code in the *closure*, which is an
anonymous function we define and pass as an argument to `unwrap_or_else`. Well
cover closures in more detail in Chapter 13. For now, you just need to know
that `unwrap_or_else` will pass the inner value of the `Err`, which in this
case is the static string `not enough arguments` that we added in Listing 12-9,
case is the static string `not enough arguments` that we added in [Listing 12-9][Listing-12-9],
to our closure in the argument `err` that appears between the vertical pipes.
The code in the closure can then use the `err` value when it runs.
@ -425,7 +443,7 @@ code in the closure that will be run in the error case is only two lines: we
print the `err` value and then call `process::exit`. The `process::exit`
function will stop the program immediately and return the number that was
passed as the exit status code. This is similar to the `panic!`-based handling
we used in Listing 12-8, but we no longer get all the extra output. Lets try
we used in [Listing 12-8][Listing-12-8], but we no longer get all the extra output. Lets try
it:
```text
@ -448,12 +466,15 @@ configuration or handling errors. When were done, `main` will be concise and
easy to verify by inspection, and well be able to write tests for all the
other logic.
Listing 12-11 shows the extracted `run` function. For now, were just making
[Listing 12-11][Listing-12-11] shows the extracted `run` function. For now, were just making
the small, incremental improvement of extracting the function. Were still
defining the function in *src/main.rs*.
<span class="filename">Filename: src/main.rs</span>
[Listing-12-11]: #Listing-12-11
<a name="Listing-12-11"></a>
```rust,ignore
fn main() {
// --snip--
@ -487,15 +508,18 @@ argument.
#### Returning Errors from the `run` Function
With the remaining program logic separated into the `run` function, we can
improve the error handling, as we did with `Config::new` in Listing 12-9.
improve the error handling, as we did with `Config::new` in [Listing 12-9][Listing-12-9].
Instead of allowing the program to panic by calling `expect`, the `run`
function will return a `Result<T, E>` when something goes wrong. This will let
us further consolidate into `main` the logic around handling errors in a
user-friendly way. Listing 12-12 shows the changes we need to make to the
user-friendly way. [Listing 12-12][Listing-12-12] shows the changes we need to make to the
signature and body of `run`.
<span class="filename">Filename: src/main.rs</span>
[Listing-12-12]: #Listing-12-12
<a name="Listing-12-12"></a>
```rust,ignore
use std::error::Error;
@ -559,7 +583,7 @@ have some error-handling code here! Lets rectify that problem now.
#### Handling Errors Returned from `run` in `main`
Well check for errors and handle them using a technique similar to one we used
with `Config::new` in Listing 12-10, but with a slight difference:
with `Config::new` in [Listing 12-10][Listing-12-10], but with a slight difference:
<span class="filename">Filename: src/main.rs</span>
@ -602,12 +626,15 @@ Lets move all the code that isnt the `main` function from *src/main.rs* to
* The definition of `Config`
* The `Config::new` function definition
The contents of *src/lib.rs* should have the signatures shown in Listing 12-13
The contents of *src/lib.rs* should have the signatures shown in [Listing 12-13][Listing-12-13]
(weve omitted the bodies of the functions for brevity). Note that this wont
compile until we modify *src/main.rs* in Listing 12-14.
compile until we modify *src/main.rs* in [Listing 12-14][Listing-12-14].
<span class="filename">Filename: src/lib.rs</span>
[Listing-12-13]: #Listing-12-13
<a name="Listing-12-13"></a>
```rust,ignore
use std::error::Error;
use std::fs::File;
@ -637,10 +664,13 @@ Weve made liberal use of the `pub` keyword: on `Config`, on its fields and it
public API that we can test!
Now we need to bring the code we moved to *src/lib.rs* into the scope of the
binary crate in *src/main.rs*, as shown in Listing 12-14.
binary crate in *src/main.rs*, as shown in [Listing 12-14][Listing-12-14].
<span class="filename">Filename: src/main.rs</span>
[Listing-12-14]: #Listing-12-14
<a name="Listing-12-14"></a>
```rust,ignore
extern crate minigrep;
@ -673,3 +703,15 @@ modular. Almost all of our work will be done in *src/lib.rs* from here on out.
Lets take advantage of this newfound modularity by doing something that would
have been difficult with the old code but is easy with the new code: well
write some tests!
[Listing-12-5]: ch12-03-improving-error-handling-and-modularity.html#Listing-12-5
[Listing-12-6]: ch12-03-improving-error-handling-and-modularity.html#Listing-12-6
[Listing-12-7]: ch12-03-improving-error-handling-and-modularity.html#Listing-12-7
[Listing-12-8]: ch12-03-improving-error-handling-and-modularity.html#Listing-12-8
[Listing-12-9]: ch12-03-improving-error-handling-and-modularity.html#Listing-12-9
[Listing-12-10]: ch12-03-improving-error-handling-and-modularity.html#Listing-12-10
[Listing-12-11]: ch12-03-improving-error-handling-and-modularity.html#Listing-12-11
[Listing-12-12]: ch12-03-improving-error-handling-and-modularity.html#Listing-12-12
[Listing-12-13]: ch12-03-improving-error-handling-and-modularity.html#Listing-12-13
[Listing-12-14]: ch12-03-improving-error-handling-and-modularity.html#Listing-12-14
[Listing-9-9]: ch09-03-to-panic-or-not-to-panic.html#Listing-9-9

View File

@ -35,10 +35,13 @@ Then, in *src/lib.rs*, well add a `test` module with a test function, as we
did in Chapter 11. The test function specifies the behavior we want the
`search` function to have: it will take a query and the text to search for the
query in, and it will return only the lines from the text that contain the
query. Listing 12-15 shows this test, which wont compile yet.
query. [Listing 12-15][Listing-12-15] shows this test, which wont compile yet.
<span class="filename">Filename: src/lib.rs</span>
[Listing-12-15]: #Listing-12-15
<a name="Listing-12-15"></a>
```rust
# fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
# vec![]
@ -74,12 +77,15 @@ from the `search` function contains only the line we expect.
We arent able to run this test and watch it fail because the test doesnt even
compile: the `search` function doesnt exist yet! So now well add just enough
code to get the test to compile and run by adding a definition of the `search`
function that always returns an empty vector, as shown in Listing 12-16. Then
function that always returns an empty vector, as shown in [Listing 12-16][Listing-12-16]. Then
the test should compile and fail because an empty vector doesnt match a vector
containing the line `"safe, fast, productive."`
<span class="filename">Filename: src/lib.rs</span>
[Listing-12-16]: #Listing-12-16
<a name="Listing-12-16"></a>
```rust
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
vec![]
@ -176,11 +182,14 @@ Lets work through each step, starting with iterating through lines.
#### Iterating Through Lines with the `lines` Method
Rust has a helpful method to handle line-by-line iteration of strings,
conveniently named `lines`, that works as shown in Listing 12-17. Note this
conveniently named `lines`, that works as shown in [Listing 12-17][Listing-12-17]. Note this
wont compile yet.
<span class="filename">Filename: src/lib.rs</span>
[Listing-12-17]: #Listing-12-17
<a name="Listing-12-17"></a>
```rust,ignore
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
for line in contents.lines() {
@ -193,8 +202,8 @@ pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
</span>
The `lines` method returns an iterator. Well talk about iterators in depth in
Chapter 13, but recall that you saw this way of using an iterator in Listing
3-5, where we used a `for` loop with an iterator to run some code on each item
Chapter 13, but recall that you saw this way of using an iterator in [Listing 3-5][Listing-3-5],
where we used a `for` loop with an iterator to run some code on each item
in a collection.
#### Searching Each Line for the Query
@ -202,10 +211,13 @@ in a collection.
Next, well check whether the current line contains our query string.
Fortunately, strings have a helpful method named `contains` that does this for
us! Add a call to the `contains` method in the `search` function, as shown in
Listing 12-18. Note this still wont compile yet.
[Listing 12-18][Listing-12-18]. Note this still wont compile yet.
<span class="filename">Filename: src/lib.rs</span>
[Listing-12-18]: #Listing-12-18
<a name="Listing-12-18"></a>
```rust,ignore
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
for line in contents.lines() {
@ -224,10 +236,13 @@ line contains the string in `query`</span>
We also need a way to store the lines that contain our query string. For that,
we can make a mutable vector before the `for` loop and call the `push` method
to store a `line` in the vector. After the `for` loop, we return the vector, as
shown in Listing 12-19.
shown in [Listing 12-19][Listing-12-19].
<span class="filename">Filename: src/lib.rs</span>
[Listing-12-19]: #Listing-12-19
<a name="Listing-12-19"></a>
```rust,ignore
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
let mut results = Vec::new();
@ -330,3 +345,10 @@ and output, lifetimes, testing, and command line parsing.
To round out this project, well briefly demonstrate how to work with
environment variables and how to print to standard error, both of which are
useful when youre writing command line programs.
[Listing-3-5]: ch03-05-control-flow.html#Listing-3-5
[Listing-12-15]: ch12-04-testing-the-librarys-functionality.html#Listing-12-15
[Listing-12-16]: ch12-04-testing-the-librarys-functionality.html#Listing-12-16
[Listing-12-17]: ch12-04-testing-the-librarys-functionality.html#Listing-12-17
[Listing-12-18]: ch12-04-testing-the-librarys-functionality.html#Listing-12-18
[Listing-12-19]: ch12-04-testing-the-librarys-functionality.html#Listing-12-19

View File

@ -14,10 +14,13 @@ the environment variable is on. Well continue to follow the TDD process, so
the first step is again to write a failing test. Well add a new test for the
new `search_case_insensitive` function and rename our old test from
`one_result` to `case_sensitive` to clarify the differences between the two
tests, as shown in Listing 12-20.
tests, as shown in [Listing 12-20][Listing-12-20].
<span class="filename">Filename: src/lib.rs</span>
[Listing-12-20]: #Listing-12-20
<a name="Listing-12-20"></a>
```rust
#[cfg(test)]
mod test {
@ -72,17 +75,20 @@ should match the line containing `"Rust:"` with a capital R and match the line
our failing test, and it will fail to compile because we havent yet defined
the `search_case_insensitive` function. Feel free to add a skeleton
implementation that always returns an empty vector, similar to the way we did
for the `search` function in Listing 12-16 to see the test compile and fail.
for the `search` function in [Listing 12-16][Listing-12-16] to see the test compile and fail.
### Implementing the `search_case_insensitive` Function
The `search_case_insensitive` function, shown in Listing 12-21, will be almost
The `search_case_insensitive` function, shown in [Listing 12-21][Listing-12-21], will be almost
the same as the `search` function. The only difference is that well lowercase
the `query` and each `line` so whatever the case of the input arguments,
theyll be the same case when we check whether the line contains the query.
<span class="filename">Filename: src/lib.rs</span>
[Listing-12-21]: #Listing-12-21
<a name="Listing-12-21"></a>
```rust
pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
let query = query.to_lowercase();
@ -148,11 +154,14 @@ pub struct Config {
Note that we added the `case_sensitive` field that holds a Boolean. Next, we
need the `run` function to check the `case_sensitive` fields value and use
that to decide whether to call the `search` function or the
`search_case_insensitive` function, as shown in Listing 12-22. Note this still
`search_case_insensitive` function, as shown in [Listing 12-22][Listing-12-22]. Note this still
wont compile yet.
<span class="filename">Filename: src/lib.rs</span>
[Listing-12-22]: #Listing-12-22
<a name="Listing-12-22"></a>
```rust
# use std::error::Error;
# use std::fs::File;
@ -200,10 +209,13 @@ working with environment variables are in the `env` module in the standard
library, so we want to bring that module into scope with a `use std::env;` line
at the top of *src/lib.rs*. Then well use the `var` function from the `env`
module to check for an environment variable named `CASE_INSENSITIVE`, as shown
in Listing 12-23.
in [Listing 12-23][Listing-12-23].
<span class="filename">Filename: src/lib.rs</span>
[Listing-12-23]: #Listing-12-23
<a name="Listing-12-23"></a>
```rust
use std::env;
# struct Config {
@ -250,7 +262,7 @@ of the other methods weve seen on `Result`.
We pass the value in the `case_sensitive` variable to the `Config` instance so
the `run` function can read that value and decide whether to call `search` or
`search_case_insensitive`, as we implemented in Listing 12-22.
`search_case_insensitive`, as we implemented in [Listing 12-22][Listing-12-22].
Lets give it a try! First, well run our program without the environment
variable set and with the query `to`, which should match any line that contains
@ -303,3 +315,9 @@ one set to case insensitive.
The `std::env` module contains many more useful features for dealing with
environment variables: check out its documentation to see what is available.
[Listing-12-20]: ch12-05-working-with-environment-variables.html#Listing-12-20
[Listing-12-21]: ch12-05-working-with-environment-variables.html#Listing-12-21
[Listing-12-22]: ch12-05-working-with-environment-variables.html#Listing-12-22
[Listing-12-23]: ch12-05-working-with-environment-variables.html#Listing-12-23
[Listing-12-16]: ch12-04-testing-the-librarys-functionality.html#Listing-12-16

View File

@ -47,7 +47,7 @@ data from a successful run ends up in the file. Well change that.
### Printing Errors to Standard Error
Well use the code in Listing 12-24 to change how error messages are printed.
Well use the code in [Listing 12-24][Listing-12-24] to change how error messages are printed.
Because of the refactoring we did earlier in this chapter, all the code that
prints error messages is in one function, `main`. The standard library provides
the `eprintln!` macro that prints to the standard error stream, so lets change
@ -56,6 +56,9 @@ instead.
<span class="filename">Filename: src/main.rs</span>
[Listing-12-24]: #Listing-12-24
<a name="Listing-12-24"></a>
```rust,ignore
fn main() {
let args: Vec<String> = env::args().collect();
@ -119,3 +122,5 @@ well tested.
Next, well explore some Rust features that were influenced by functional
languages: closures and iterators.
[Listing-12-24]: ch12-06-writing-to-stderr-instead-of-stdout.html#Listing-12-24

View File

@ -23,12 +23,15 @@ few seconds. We want to call this algorithm only when we need to and only call
it once so we dont make the user wait more than necessary.
Well simulate calling this hypothetical algorithm with the function
`simulated_expensive_calculation` shown in Listing 13-1, which will print
`simulated_expensive_calculation` shown in [Listing 13-1][Listing-13-1], which will print
`calculating slowly...`, wait for two seconds, and then return whatever number
we passed in.
<span class="filename">Filename: src/main.rs</span>
[Listing-13-1]: #Listing-13-1
<a name="Listing-13-1"></a>
```rust
use std::thread;
use std::time::Duration;
@ -56,11 +59,14 @@ The required inputs are these:
high-intensity workout
* A random number that will generate some variety in the workout plans
The output will be the recommended workout plan. Listing 13-2 shows the `main`
The output will be the recommended workout plan. [Listing 13-2][Listing-13-2] shows the `main`
function well use.
<span class="filename">Filename: src/main.rs</span>
[Listing-13-2]: #Listing-13-2
<a name="Listing-13-2"></a>
```rust
fn main() {
let simulated_user_specified_value = 10;
@ -85,12 +91,15 @@ example in Chapter 2. The `main` function calls a `generate_workout` function
with the simulated input values.
Now that we have the context, lets get to the algorithm. The function
`generate_workout` in Listing 13-3 contains the business logic of the
`generate_workout` in [Listing 13-3][Listing-13-3] contains the business logic of the
app that were most concerned with in this example. The rest of the code
changes in this example will be made to this function.
<span class="filename">Filename: src/main.rs</span>
[Listing-13-3]: #Listing-13-3
<a name="Listing-13-3"></a>
```rust
# use std::thread;
# use std::time::Duration;
@ -128,7 +137,7 @@ fn generate_workout(intensity: u32, random_number: u32) {
plans based on the inputs and calls to the `simulated_expensive_calculation`
function</span>
The code in Listing 13-3 has multiple calls to the slow calculation function.
The code in [Listing 13-3][Listing-13-3] has multiple calls to the slow calculation function.
The first `if` block calls `simulated_expensive_calculation` twice, the `if`
inside the outer `else` doesnt call it at all, and the code inside the
second `else` case calls it once.
@ -160,10 +169,13 @@ to call it if the result isnt needed, and we still want to call it only once.
We could restructure the workout program in many ways. First, well try
extracting the duplicated call to the `simulated_expensive_calculation`
function into a variable, as shown in Listing 13-4.
function into a variable, as shown in [Listing 13-4][Listing-13-4].
<span class="filename">Filename: src/main.rs</span>
[Listing-13-4]: #Listing-13-4
<a name="Listing-13-4"></a>
```rust
# use std::thread;
# use std::time::Duration;
@ -217,12 +229,15 @@ code where we actually need the result. This is a use case for closures!
Instead of always calling the `simulated_expensive_calculation` function before
the `if` blocks, we can define a closure and store the *closure* in a variable
rather than storing the result of the function call, as shown in Listing 13-5.
rather than storing the result of the function call, as shown in [Listing 13-5][Listing-13-5].
We can actually move the whole body of `simulated_expensive_calculation` within
the closure were introducing here.
<span class="filename">Filename: src/main.rs</span>
[Listing-13-5]: #Listing-13-5
<a name="Listing-13-5"></a>
```rust
# use std::thread;
# use std::time::Duration;
@ -262,10 +277,13 @@ With the closure defined, we can change the code in the `if` blocks to call the
closure to execute the code and get the resulting value. We call a closure like
we do a function: we specify the variable name that holds the closure
definition and follow it with parentheses containing the argument values we
want to use, as shown in Listing 13-6.
want to use, as shown in [Listing 13-6][Listing-13-6].
<span class="filename">Filename: src/main.rs</span>
[Listing-13-6]: #Listing-13-6
<a name="Listing-13-6"></a>
```rust
# use std::thread;
# use std::time::Duration;
@ -305,7 +323,7 @@ defined</span>
Now the expensive calculation is called in only one place, and were only
executing that code where we need the results.
However, weve reintroduced one of the problems from Listing 13-3: were still
However, weve reintroduced one of the problems from [Listing 13-3][Listing-13-3]: were still
calling the closure twice in the first `if` block, which will call the
expensive code twice and make the user wait twice as long as they need to. We
could fix this problem by creating a variable local to that `if` block to hold
@ -335,11 +353,14 @@ available.
As with variables, we can add type annotations if we want to increase
explicitness and clarity at the cost of being more verbose than is strictly
necessary. Annotating the types for the closure we defined in Listing 13-5
would look like the definition shown in Listing 13-7.
necessary. Annotating the types for the closure we defined in [Listing 13-5][Listing-13-5]
would look like the definition shown in [Listing 13-7][Listing-13-7].
<span class="filename">Filename: src/main.rs</span>
[Listing-13-7]: #Listing-13-7
<a name="Listing-13-7"></a>
```rust
# use std::thread;
# use std::time::Duration;
@ -375,7 +396,7 @@ optional because the closure body has only one expression. These are all valid
definitions that will produce the same behavior when theyre called.
Closure definitions will have one concrete type inferred for each of their
parameters and for their return value. For instance, Listing 13-8 shows the
parameters and for their return value. For instance, [Listing 13-8][Listing-13-8] shows the
definition of a short closure that just returns the value it receives as a
parameter. This closure isnt very useful except for the purposes of this
example. Note that we havent added any type annotations to the definition: if
@ -384,6 +405,9 @@ first time and a `u32` the second time, well get an error.
<span class="filename">Filename: src/main.rs</span>
[Listing-13-8]: #Listing-13-8
<a name="Listing-13-8"></a>
```rust,ignore
let example_closure = |x| x;
@ -415,7 +439,7 @@ error if we try to use a different type with the same closure.
### Storing Closures Using Generic Parameters and the `Fn` Traits
Lets return to our workout generation app. In Listing 13-6, our code was still
Lets return to our workout generation app. In [Listing 13-6][Listing-13-6], our code was still
calling the expensive calculation closure more times than it needed to. One
option to solve this issue is to save the result of the expensive closure in a
variable for reuse and use the variable in each place we need the result,
@ -446,11 +470,14 @@ and return values the closures must have to match this trait bound. In this
case, our closure has a parameter of type `u32` and returns a `u32`, so the
trait bound we specify is `Fn(u32) -> u32`.
Listing 13-9 shows the definition of the `Cacher` struct that holds a closure
[Listing 13-9][Listing-13-9] shows the definition of the `Cacher` struct that holds a closure
and an optional result value.
<span class="filename">Filename: src/main.rs</span>
[Listing-13-9]: #Listing-13-9
<a name="Listing-13-9"></a>
```rust
struct Cacher<T>
where T: Fn(u32) -> u32
@ -481,11 +508,13 @@ result within a `Some` variant in the `value` field. Then if the code asks for
the result of the closure again, instead of executing the closure again, the
`Cacher` will return the result held in the `Some` variant.
The logic around the `value` field weve just described is defined in Listing
13-10.
The logic around the `value` field weve just described is defined in [Listing 13-10][Listing-13-10].
<span class="filename">Filename: src/main.rs</span>
[Listing-13-10]: #Listing-13-10
<a name="Listing-13-10"></a>
```rust
# struct Cacher<T>
# where T: Fn(u32) -> u32
@ -539,11 +568,14 @@ If `self.value` is `None`, the code calls the closure stored in
`self.calculation`, saves the result in `self.value` for future use, and
returns the value as well.
Listing 13-11 shows how we can use this `Cacher` struct in the function
`generate_workout` from Listing 13-6.
[Listing 13-11][Listing-13-11] shows how we can use this `Cacher` struct in the function
`generate_workout` from [Listing 13-6][Listing-13-6].
<span class="filename">Filename: src/main.rs</span>
[Listing-13-11]: #Listing-13-11
<a name="Listing-13-11"></a>
```rust
# use std::thread;
# use std::time::Duration;
@ -615,7 +647,7 @@ call the `value` method on the `Cacher` instance. We can call the `value`
method as many times as we want, or not call it at all, and the expensive
calculation will be run a maximum of once.
Try running this program with the `main` function from Listing 13-2. Change the
Try running this program with the `main` function from [Listing 13-2][Listing-13-2]. Change the
values in the `simulated_user_specified_value` and `simulated_random_number`
variables to verify that in all the cases in the various `if` and `else`
blocks, `calculating slowly...` appears only once and only when needed. The
@ -651,8 +683,8 @@ passed into it. We call the `value` method on this `Cacher` instance with an
`arg` value of 1 and then an `arg` value of 2, and we expect the call to
`value` with the `arg` value of 2 to return 2.
Run this test with the `Cacher` implementation in Listing 13-9 and Listing
13-10, and the test will fail on the `assert_eq!` with this message:
Run this test with the `Cacher` implementation in [Listing 13-9][Listing-13-9] and [Listing 13-10][Listing-13-10],
and the test will fail on the `assert_eq!` with this message:
```text
thread 'call_with_different_values' panicked at 'assertion failed: `(left == right)`
@ -685,11 +717,14 @@ functions. However, closures have an additional capability that functions don
have: they can capture their environment and access variables from the scope in
which theyre defined.
Listing 13-12 has an example of a closure stored in the `equal_to_x` variable
[Listing 13-12][Listing-13-12] has an example of a closure stored in the `equal_to_x` variable
that uses the `x` variable from the closures surrounding environment.
<span class="filename">Filename: src/main.rs</span>
[Listing-13-12]: #Listing-13-12
<a name="Listing-13-12"></a>
```rust
fn main() {
let x = 4;
@ -763,7 +798,7 @@ When you create a closure, Rust infers which trait to use based on how the
closure uses the values from the environment. All closures implement `FnOnce`
because they can all be called at least once. Closures that dont move the
captured variables also implement `FnMut`, and closures that dont need mutable
access to the captured variables also implement `Fn`. In Listing 13-12, the
access to the captured variables also implement `Fn`. In [Listing 13-12][Listing-13-12], the
`equal_to_x` closure borrows `x` immutably (so `equal_to_x` has the `Fn` trait)
because the body of the closure only needs to read the value in `x`.
@ -773,7 +808,7 @@ technique is mostly useful when passing a closure to a new thread to move the
data so its owned by the new thread.
Well have more examples of `move` closures in Chapter 16 when we talk about
concurrency. For now, heres the code from Listing 13-12 with the `move`
concurrency. For now, heres the code from [Listing 13-12][Listing-13-12] with the `move`
keyword added to the closure definition and using vectors instead of integers,
because integers can be copied rather than moved; note that this code will not
yet compile.
@ -821,3 +856,16 @@ on what happens in the closure body.
To illustrate situations where closures that can capture their environment are
useful as function parameters, lets move on to our next topic: iterators.
[Listing-13-1]: ch13-01-closures.html#Listing-13-1
[Listing-13-2]: ch13-01-closures.html#Listing-13-2
[Listing-13-3]: ch13-01-closures.html#Listing-13-3
[Listing-13-4]: ch13-01-closures.html#Listing-13-4
[Listing-13-5]: ch13-01-closures.html#Listing-13-5
[Listing-13-6]: ch13-01-closures.html#Listing-13-6
[Listing-13-7]: ch13-01-closures.html#Listing-13-7
[Listing-13-8]: ch13-01-closures.html#Listing-13-8
[Listing-13-9]: ch13-01-closures.html#Listing-13-9
[Listing-13-10]: ch13-01-closures.html#Listing-13-10
[Listing-13-11]: ch13-01-closures.html#Listing-13-11
[Listing-13-12]: ch13-01-closures.html#Listing-13-12

View File

@ -7,10 +7,13 @@ have to reimplement that logic yourself.
In Rust, iterators are *lazy*, meaning they have no effect until you call
methods that consume the iterator to use it up. For example, the code in
Listing 13-13 creates an iterator over the items in the vector `v1` by calling
[Listing 13-13][Listing-13-13] creates an iterator over the items in the vector `v1` by calling
the `iter` method defined on `Vec<T>`. This code by itself doesnt do anything
useful.
[Listing-13-13]: #Listing-13-13
<a name="Listing-13-13"></a>
```rust
let v1 = vec![1, 2, 3];
@ -19,16 +22,19 @@ let v1_iter = v1.iter();
<span class="caption">Listing 13-13: Creating an iterator</span>
Once weve created an iterator, we can use it in a variety of ways. In Listing
3-5 in Chapter 3, we used iterators with `for` loops to execute some code on
Once weve created an iterator, we can use it in a variety of ways. In [Listing 3-5][Listing-3-5]
in Chapter 3, we used iterators with `for` loops to execute some code on
each item, although we glossed over what the call to `iter` did until now.
The example in Listing 13-14 separates the creation of the iterator from the
The example in [Listing 13-14][Listing-13-14] separates the creation of the iterator from the
use of the iterator in the `for` loop. The iterator is stored in the `v1_iter`
variable, and no iteration takes place at that time. When the `for` loop is
called using the iterator in `v1_iter`, each element in the iterator is used in
one iteration of the loop, which prints out each value.
[Listing-13-14]: #Listing-13-14
<a name="Listing-13-14"></a>
```rust
let v1 = vec![1, 2, 3];
@ -79,12 +85,15 @@ The `Iterator` trait only requires implementors to define one method: the
`next` method, which returns one item of the iterator at a time wrapped in
`Some` and, when iteration is over, returns `None`.
We can call the `next` method on iterators directly; Listing 13-15 demonstrates
We can call the `next` method on iterators directly; [Listing 13-15][Listing-13-15] demonstrates
what values are returned from repeated calls to `next` on the iterator created
from the vector.
<span class="filename">Filename: src/lib.rs</span>
[Listing-13-15]: #Listing-13-15
<a name="Listing-13-15"></a>
```rust
#[test]
fn iterator_demonstration() {
@ -129,11 +138,14 @@ Methods that call `next` are called *consuming adaptors*, because calling them
uses up the iterator. One example is the `sum` method, which takes ownership of
the iterator and iterates through the items by repeatedly calling `next`, thus
consuming the iterator. As it iterates through, it adds each item to a running
total and returns the total when iteration is complete. Listing 13-16 has a
total and returns the total when iteration is complete. [Listing 13-16][Listing-13-16] has a
test illustrating a use of the `sum` method:
<span class="filename">Filename: src/lib.rs</span>
[Listing-13-16]: #Listing-13-16
<a name="Listing-13-16"></a>
```rust
#[test]
fn iterator_sum() {
@ -161,13 +173,16 @@ multiple calls to iterator adaptors to perform complex actions in a readable
way. But because all iterators are lazy, you have to call one of the consuming
adaptor methods to get results from calls to iterator adaptors.
Listing 13-17 shows an example of calling the iterator adaptor method `map`,
[Listing 13-17][Listing-13-17] shows an example of calling the iterator adaptor method `map`,
which takes a closure to call on each item to produce a new iterator. The
closure here creates a new iterator in which each item from the vector has been
incremented by 1. However, this code produces a warning:
<span class="filename">Filename: src/main.rs</span>
[Listing-13-17]: #Listing-13-17
<a name="Listing-13-17"></a>
```rust
let v1: Vec<i32> = vec![1, 2, 3];
@ -190,20 +205,23 @@ and do nothing unless consumed
= note: #[warn(unused_must_use)] on by default
```
The code in Listing 13-17 doesnt do anything; the closure weve specified
The code in [Listing 13-17][Listing-13-17] doesnt do anything; the closure weve specified
never gets called. The warning reminds us why: iterator adaptors are lazy, and
we need to consume the iterator here.
To fix this and consume the iterator, well use the `collect` method, which we
used in Chapter 12 with `env::args` in Listing 12-1. This method consumes the
used in Chapter 12 with `env::args` in [Listing 12-1][Listing-12-1]. This method consumes the
iterator and collects the resulting values into a collection data type.
In Listing 13-18, we collect the results of iterating over the iterator thats
In [Listing 13-18][Listing-13-18], we collect the results of iterating over the iterator thats
returned from the call to `map` into a vector. This vector will end up
containing each item from the original vector incremented by 1.
<span class="filename">Filename: src/main.rs</span>
[Listing-13-18]: #Listing-13-18
<a name="Listing-13-18"></a>
```rust
let v1: Vec<i32> = vec![1, 2, 3];
@ -230,12 +248,15 @@ the iterator and returns a Boolean. If the closure returns `true`, the value
will be included in the iterator produced by `filter`. If the closure returns
`false`, the value wont be included in the resulting iterator.
In Listing 13-19, we use `filter` with a closure that captures the `shoe_size`
In [Listing 13-19][Listing-13-19], we use `filter` with a closure that captures the `shoe_size`
variable from its environment to iterate over a collection of `Shoe` struct
instances. It will return only shoes that are the specified size.
<span class="filename">Filename: src/lib.rs</span>
[Listing-13-19]: #Listing-13-19
<a name="Listing-13-19"></a>
```rust
#[derive(PartialEq, Debug)]
struct Shoe {
@ -305,11 +326,14 @@ First, well create a struct to hold some values. Then well make this struc
into an iterator by implementing the `Iterator` trait and using the values in
that implementation.
Listing 13-20 has the definition of the `Counter` struct and an associated
[Listing 13-20][Listing-13-20] has the definition of the `Counter` struct and an associated
`new` function to create instances of `Counter`:
<span class="filename">Filename: src/lib.rs</span>
[Listing-13-20]: #Listing-13-20
<a name="Listing-13-20"></a>
```rust
struct Counter {
count: u32,
@ -334,10 +358,13 @@ always starting new instances with a value of 0 in the `count` field.
Next, well implement the `Iterator` trait for our `Counter` type by defining
the body of the `next` method to specify what we want to happen when this
iterator is used, as shown in Listing 13-21:
iterator is used, as shown in [Listing 13-21][Listing-13-21]:
<span class="filename">Filename: src/lib.rs</span>
[Listing-13-21]: #Listing-13-21
<a name="Listing-13-21"></a>
```rust
# struct Counter {
# count: u32,
@ -372,13 +399,16 @@ our iterator will return `None`.
#### Using Our `Counter` Iterators `next` Method
Once weve implemented the `Iterator` trait, we have an iterator! Listing 13-22
Once weve implemented the `Iterator` trait, we have an iterator! [Listing 13-22][Listing-13-22]
shows a test demonstrating that we can use the iterator functionality of our
`Counter` struct by calling the `next` method on it directly, just as we did
with the iterator created from a vector in Listing 13-15.
with the iterator created from a vector in [Listing 13-15][Listing-13-15].
<span class="filename">Filename: src/lib.rs</span>
[Listing-13-22]: #Listing-13-22
<a name="Listing-13-22"></a>
```rust
# struct Counter {
# count: u32,
@ -428,10 +458,13 @@ For example, if for some reason we wanted to take the values produced by an
instance of `Counter`, pair them with values produced by another `Counter`
instance after skipping the first value, multiply each pair together, keep only
those results that are divisible by 3, and add all the resulting values
together, we could do so, as shown in the test in Listing 13-23:
together, we could do so, as shown in the test in [Listing 13-23][Listing-13-23]:
<span class="filename">Filename: src/lib.rs</span>
[Listing-13-23]: #Listing-13-23
<a name="Listing-13-23"></a>
```rust
# struct Counter {
# count: u32,
@ -480,3 +513,17 @@ iterators return `None`.
All of these method calls are possible because we specified how the `next`
method works, and the standard library provides default implementations for
other methods that call `next`.
[Listing-12-1]: ch12-01-accepting-command-line-arguments.html#Listing-12-1
[Listing-13-13]: ch13-02-iterators.html#Listing-13-13
[Listing-13-14]: ch13-02-iterators.html#Listing-13-14
[Listing-13-15]: ch13-02-iterators.html#Listing-13-15
[Listing-13-16]: ch13-02-iterators.html#Listing-13-16
[Listing-13-17]: ch13-02-iterators.html#Listing-13-17
[Listing-13-18]: ch13-02-iterators.html#Listing-13-18
[Listing-13-19]: ch13-02-iterators.html#Listing-13-19
[Listing-13-20]: ch13-02-iterators.html#Listing-13-20
[Listing-13-21]: ch13-02-iterators.html#Listing-13-21
[Listing-13-22]: ch13-02-iterators.html#Listing-13-22
[Listing-13-23]: ch13-02-iterators.html#Listing-13-23
[Listing-3-5]: ch03-05-control-flow.html#Listing-3-5

View File

@ -8,14 +8,17 @@ concise. Lets look at how iterators can improve our implementation of the
### Removing a `clone` Using an Iterator
In Listing 12-6, we added code that took a slice of `String` values and created
In [Listing 12-6][Listing-12-6], we added code that took a slice of `String` values and created
an instance of the `Config` struct by indexing into the slice and cloning the
values, allowing the `Config` struct to own those values. In Listing 13-24,
values, allowing the `Config` struct to own those values. In [Listing 13-24][Listing-13-24],
weve reproduced the implementation of the `Config::new` function as it was in
Listing 12-23:
[Listing 12-23][Listing-12-23]:
<span class="filename">Filename: src/lib.rs</span>
[Listing-13-24]: #Listing-13-24
<a name="Listing-13-24"></a>
```rust,ignore
impl Config {
pub fn new(args: &[String]) -> Result<Config, &'static str> {
@ -34,7 +37,7 @@ impl Config {
```
<span class="caption">Listing 13-24: Reproduction of the `Config::new` function
from Listing 12-23</span>
from [Listing 12-23][Listing-12-23]</span>
At the time, we said not to worry about the inefficient `clone` calls because
we would remove them in the future. Well, that time is now!
@ -73,12 +76,15 @@ fn main() {
}
```
Well change the start of the `main` function that we had in Listing 12-24 at
to the code in Listing 13-25. This wont compile until we update `Config::new`
Well change the start of the `main` function that we had in [Listing 12-24][Listing-12-24] at
to the code in [Listing 13-25][Listing-13-25]. This wont compile until we update `Config::new`
as well.
<span class="filename">Filename: src/main.rs</span>
[Listing-13-25]: #Listing-13-25
<a name="Listing-13-25"></a>
```rust,ignore
fn main() {
let config = Config::new(env::args()).unwrap_or_else(|err| {
@ -100,11 +106,14 @@ were passing ownership of the iterator returned from `env::args` to
Next, we need to update the definition of `Config::new`. In your I/O projects
*src/lib.rs* file, lets change the signature of `Config::new` to look like
Listing 13-26. This still wont compile because we need to update the function
[Listing 13-26][Listing-13-26]. This still wont compile because we need to update the function
body.
<span class="filename">Filename: src/lib.rs</span>
[Listing-13-26]: #Listing-13-26
<a name="Listing-13-26"></a>
```rust,ignore
impl Config {
pub fn new(mut args: std::env::Args) -> Result<Config, &'static str> {
@ -125,11 +134,14 @@ keyword into the specification of the `args` parameter to make it mutable.
Next, well fix the body of `Config::new`. The standard library documentation
also mentions that `std::env::Args` implements the `Iterator` trait, so we know
we can call the `next` method on it! Listing 13-27 updates the code from
Listing 12-23 to use the `next` method:
we can call the `next` method on it! [Listing 13-27][Listing-13-27] updates the code from
[Listing 12-23][Listing-12-23] to use the `next` method:
<span class="filename">Filename: src/lib.rs</span>
[Listing-13-27]: #Listing-13-27
<a name="Listing-13-27"></a>
```rust
# fn main() {}
# use std::env;
@ -175,10 +187,13 @@ the same thing for the `filename` value.
### Making Code Clearer with Iterator Adaptors
We can also take advantage of iterators in the `search` function in our I/O
project, which is reproduced here in Listing 13-28 as it was in Listing 12-19:
project, which is reproduced here in [Listing 13-28][Listing-13-28] as it was in [Listing 12-19][Listing-12-19]:
<span class="filename">Filename: src/lib.rs</span>
[Listing-13-28]: #Listing-13-28
<a name="Listing-13-28"></a>
```rust,ignore
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
let mut results = Vec::new();
@ -194,17 +209,20 @@ pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
```
<span class="caption">Listing 13-28: The implementation of the `search`
function from Listing 12-19</span>
function from [Listing 12-19][Listing-12-19]</span>
We can write this code in a more concise way using iterator adaptor methods.
Doing so also lets us avoid having a mutable intermediate `results` vector. The
functional programming style prefers to minimize the amount of mutable state to
make code clearer. Removing the mutable state might enable a future enhancement
to make searching happen in parallel, because we wouldnt have to manage
concurrent access to the `results` vector. Listing 13-29 shows this change:
concurrent access to the `results` vector. [Listing 13-29][Listing-13-29] shows this change:
<span class="filename">Filename: src/lib.rs</span>
[Listing-13-29]: #Listing-13-29
<a name="Listing-13-29"></a>
```rust,ignore
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
contents.lines()
@ -217,16 +235,16 @@ pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
implementation of the `search` function</span>
Recall that the purpose of the `search` function is to return all lines in
`contents` that contain the `query`. Similar to the `filter` example in Listing
13-19, this code uses the `filter` adaptor to keep only the lines that
`contents` that contain the `query`. Similar to the `filter` example in [Listing 13-19][Listing-13-19],
this code uses the `filter` adaptor to keep only the lines that
`line.contains(query)` returns `true` for. We then collect the matching lines
into another vector with `collect`. Much simpler! Feel free to make the same
change to use iterator methods in the `search_case_insensitive` function as
well.
The next logical question is which style you should choose in your own code and
why: the original implementation in Listing 13-28 or the version using
iterators in Listing 13-29. Most Rust programmers prefer to use the iterator
why: the original implementation in [Listing 13-28][Listing-13-28] or the version using
iterators in [Listing 13-29][Listing-13-29]. Most Rust programmers prefer to use the iterator
style. Its a bit tougher to get the hang of at first, but once you get a feel
for the various iterator adaptors and what they do, iterators can be easier to
understand. Instead of fiddling with the various bits of looping and building
@ -238,3 +256,15 @@ the iterator must pass.
But are the two implementations truly equivalent? The intuitive assumption
might be that the more low-level loop will be faster. Lets talk about
performance.
[Listing-13-19]: ch13-02-iterators.html#Listing-13-19
[Listing-12-24]: ch12-06-writing-to-stderr-instead-of-stdout.html#Listing-12-24
[Listing-12-6]: ch12-03-improving-error-handling-and-modularity.html#Listing-12-6
[Listing-12-23]: ch12-05-working-with-environment-variables.html#Listing-12-23
[Listing-13-24]: ch13-03-improving-our-io-project.html#Listing-13-24
[Listing-13-25]: ch13-03-improving-our-io-project.html#Listing-13-25
[Listing-13-26]: ch13-03-improving-our-io-project.html#Listing-13-26
[Listing-13-27]: ch13-03-improving-our-io-project.html#Listing-13-27
[Listing-13-28]: ch13-03-improving-our-io-project.html#Listing-13-28
[Listing-13-29]: ch13-03-improving-our-io-project.html#Listing-13-29
[Listing-12-19]: ch12-04-testing-the-librarys-functionality.html#Listing-12-19

View File

@ -23,7 +23,7 @@ your crate is *implemented*.
Documentation comments use three slashes, `///`, instead of two and support
Markdown notation for formatting the text. Place documentation comments just
before the item theyre documenting. Listing 14-1 shows documentation comments
before the item theyre documenting. [Listing 14-1][Listing-14-1] shows documentation comments
for an `add_one` function in a crate named `my_crate`:
<span class="filename">Filename: src/lib.rs</span>
@ -37,6 +37,9 @@ for an `add_one` function in a crate named `my_crate`:
/// let five = 5;
///
/// assert_eq!(6, my_crate::add_one(5));
[Listing-14-1]: #Listing-14-1
<a name="Listing-14-1"></a>
/// ```
pub fn add_one(x: i32) -> i32 {
x + 1
@ -57,7 +60,10 @@ For convenience, running `cargo doc --open` will build the HTML for your
current crates documentation (as well as the documentation for all of your
crates dependencies) and open the result in a web browser. Navigate to the
`add_one` function and youll see how the text in the documentation comments is
rendered, as shown in Figure 14-1:
rendered, as shown in [Figure 14-1][Figure-14-1]:
[Figure-14-1]: #Figure-14-1
<a name="Figure-14-1"></a>
<img alt="Rendered HTML documentation for the `add_one` function of `my_crate`" src="img/trpl14-01.png" class="center" />
@ -66,7 +72,7 @@ function</span>
#### Commonly Used Sections
We used the `# Examples` Markdown heading in Listing 14-1 to create a section
We used the `# Examples` Markdown heading in [Listing 14-1][Listing-14-1] to create a section
in the HTML with the title “Examples.” Here are some other sections that crate
authors commonly use in their documentation:
@ -93,7 +99,7 @@ test` will run the code examples in your documentation as tests! Nothing is
better than documentation with examples. But nothing is worse than examples
that dont work because the code has changed since the documentation was
written. If we run `cargo test` with the documentation for the `add_one`
function from Listing 14-1, we will see a section in the test results like this:
function from [Listing 14-1][Listing-14-1], we will see a section in the test results like this:
```text
Doc-tests my_crate
@ -119,10 +125,13 @@ module as a whole.
For example, if we want to add documentation that describes the purpose of the
`my_crate` crate that contains the `add_one` function, we can add documentation
comments that start with `//!` to the beginning of the *src/lib.rs* file, as
shown in Listing 14-2:
shown in [Listing 14-2][Listing-14-2]:
<span class="filename">Filename: src/lib.rs</span>
[Listing-14-2]: #Listing-14-2
<a name="Listing-14-2"></a>
```rust,ignore
//! # My Crate
//!
@ -144,7 +153,10 @@ is the crate root. These comments describe the entire crate.
When we run `cargo doc --open`, these comments will display on the front
page of the documentation for `my_crate` above the list of public items in the
crate, as shown in Figure 14-2:
crate, as shown in [Figure 14-2][Figure-14-2]:
[Figure-14-2]: #Figure-14-2
<a name="Figure-14-2"></a>
<img alt="Rendered HTML documentation with a comment for the crate as a whole" src="img/trpl14-02.png" class="center" />
@ -183,10 +195,13 @@ defined in the other location instead.
For example, say we made a library named `art` for modeling artistic concepts.
Within this library are two modules: a `kinds` module containing two enums
named `PrimaryColor` and `SecondaryColor` and a `utils` module containing a
function named `mix`, as shown in Listing 14-3:
function named `mix`, as shown in [Listing 14-3][Listing-14-3]:
<span class="filename">Filename: src/lib.rs</span>
[Listing-14-3]: #Listing-14-3
<a name="Listing-14-3"></a>
```rust,ignore
//! # Art
//!
@ -222,9 +237,12 @@ pub mod utils {
<span class="caption">Listing 14-3: An `art` library with items organized into
`kinds` and `utils` modules</span>
Figure 14-3 shows what the front page of the documentation for this crate
[Figure 14-3][Figure-14-3] shows what the front page of the documentation for this crate
generated by `cargo doc` would look like:
[Figure-14-3]: #Figure-14-3
<a name="Figure-14-3"></a>
<img alt="Rendered documentation for the `art` crate that lists the `kinds` and `utils` modules" src="img/trpl14-03.png" class="center" />
<span class="caption">Figure 14-3: Front page of the documentation for `art`
@ -236,11 +254,14 @@ see them.
Another crate that depends on this library would need `use` statements that
import the items from `art`, specifying the module structure thats currently
defined. Listing 14-4 shows an example of a crate that uses the `PrimaryColor`
defined. [Listing 14-4][Listing-14-4] shows an example of a crate that uses the `PrimaryColor`
and `mix` items from the `art` crate:
<span class="filename">Filename: src/main.rs</span>
[Listing-14-4]: #Listing-14-4
<a name="Listing-14-4"></a>
```rust,ignore
extern crate art;
@ -257,7 +278,7 @@ fn main() {
<span class="caption">Listing 14-4: A crate using the `art` crates items with
its internal structure exported</span>
The author of the code in Listing 14-4, which uses the `art` crate, had to
The author of the code in [Listing 14-4][Listing-14-4], which uses the `art` crate, had to
figure out that `PrimaryColor` is in the `kinds` module and `mix` is in the
`utils` module. The module structure of the `art` crate is more relevant to
developers working on the `art` crate than to developers using the `art` crate.
@ -269,11 +290,14 @@ where to look, and the structure is inconvenient because developers must
specify the module names in the `use` statements.
To remove the internal organization from the public API, we can modify the
`art` crate code in Listing 14-3 to add `pub use` statements to re-export the
items at the top level, as shown in Listing 14-5:
`art` crate code in [Listing 14-3][Listing-14-3] to add `pub use` statements to re-export the
items at the top level, as shown in [Listing 14-5][Listing-14-5]:
<span class="filename">Filename: src/lib.rs</span>
[Listing-14-5]: #Listing-14-5
<a name="Listing-14-5"></a>
```rust,ignore
//! # Art
//!
@ -296,20 +320,26 @@ pub mod utils {
items</span>
The API documentation that `cargo doc` generates for this crate will now list
and link re-exports on the front page, as shown in Figure 14-4, making the
and link re-exports on the front page, as shown in [Figure 14-4][Figure-14-4], making the
`PrimaryColor` and `SecondaryColor` types and the `mix` function easier to find.
[Figure-14-4]: #Figure-14-4
<a name="Figure-14-4"></a>
<img alt="Rendered documentation for the `art` crate with the re-exports on the front page" src="img/trpl14-04.png" class="center" />
<span class="caption">Figure 14-4: The front page of the documentation for `art`
that lists the re-exports</span>
The `art` crate users can still see and use the internal structure from Listing
14-3 as demonstrated in Listing 14-4, or they can use the more convenient
structure in Listing 14-5, as shown in Listing 14-6:
The `art` crate users can still see and use the internal structure from [Listing 14-3][Listing-14-3]
as demonstrated in [Listing 14-4][Listing-14-4], or they can use the more convenient
structure in [Listing 14-5][Listing-14-5], as shown in [Listing 14-6][Listing-14-6]:
<span class="filename">Filename: src/main.rs</span>
[Listing-14-6]: #Listing-14-6
<a name="Listing-14-6"></a>
```rust,ignore
extern crate art;
@ -514,3 +544,14 @@ $ cargo yank --vers 1.0.1 --undo
A yank *does not* delete any code. For example, the yank feature is not
intended for deleting accidentally uploaded secrets. If that happens, you must
reset those secrets immediately.
[Listing-14-1]: ch14-02-publishing-to-crates-io.html#Listing-14-1
[Figure-14-1]: ch14-02-publishing-to-crates-io.html#Figure-14-1
[Listing-14-2]: ch14-02-publishing-to-crates-io.html#Listing-14-2
[Figure-14-2]: ch14-02-publishing-to-crates-io.html#Figure-14-2
[Listing-14-3]: ch14-02-publishing-to-crates-io.html#Listing-14-3
[Figure-14-3]: ch14-02-publishing-to-crates-io.html#Figure-14-3
[Listing-14-4]: ch14-02-publishing-to-crates-io.html#Listing-14-4
[Listing-14-5]: ch14-02-publishing-to-crates-io.html#Listing-14-5
[Figure-14-4]: ch14-02-publishing-to-crates-io.html#Figure-14-4
[Listing-14-6]: ch14-02-publishing-to-crates-io.html#Listing-14-6

View File

@ -140,10 +140,13 @@ we need to be explicit about the dependency relationships between the crates.
Next, lets use the `add_one` function from the `add-one` crate in the `adder`
crate. Open the *adder/src/main.rs* file and add an `extern crate` line at
the top to bring the new `add-one` library crate into scope. Then change the
`main` function to call the `add_one` function, as in Listing 14-7:
`main` function to call the `add_one` function, as in [Listing 14-7][Listing-14-7]:
<span class="filename">Filename: adder/src/main.rs</span>
[Listing-14-7]: #Listing-14-7
<a name="Listing-14-7"></a>
```rust,ignore
extern crate add_one;
@ -334,3 +337,5 @@ As your project grows, consider using a workspace: its easier to understand
smaller, individual components than one big blob of code. Furthermore, keeping
the crates in a workspace can make coordination between them easier if they are
often changed at the same time.
[Listing-14-7]: ch14-03-cargo-workspaces.html#Listing-14-7

View File

@ -31,10 +31,13 @@ to that topic. So what you learn here youll apply again in Chapter 17!
Before we discuss this use case for `Box<T>`, well cover the syntax and how to
interact with values stored within a `Box<T>`.
Listing 15-1 shows how to use a box to store an `i32` value on the heap:
[Listing 15-1][Listing-15-1] shows how to use a box to store an `i32` value on the heap:
<span class="filename">Filename: src/main.rs</span>
[Listing-15-1]: #Listing-15-1
<a name="Listing-15-1"></a>
```rust
fn main() {
let b = Box::new(5);
@ -100,12 +103,15 @@ complex recursive data types *are* useful in various situations, but by
starting with the cons list, we can explore how boxes let us define a recursive
data type without much distraction.
Listing 15-2 contains an enum definition for a cons list. Note that this code
[Listing 15-2][Listing-15-2] contains an enum definition for a cons list. Note that this code
wont compile yet because the `List` type doesnt have a known size, which
well demonstrate.
<span class="filename">Filename: src/main.rs</span>
[Listing-15-2]: #Listing-15-2
<a name="Listing-15-2"></a>
```rust,ignore
enum List {
Cons(i32, List),
@ -122,10 +128,13 @@ represent a cons list data structure of `i32` values</span>
> any type.
Using the `List` type to store the list `1, 2, 3` would look like the code in
Listing 15-3:
[Listing 15-3][Listing-15-3]:
<span class="filename">Filename: src/main.rs</span>
[Listing-15-3]: #Listing-15-3
<a name="Listing-15-3"></a>
```rust,ignore
use List::{Cons, Nil};
@ -142,8 +151,11 @@ another `Cons` value that holds `2` and another `List` value. This `List` value
is one more `Cons` value that holds `3` and a `List` value, which is finally
`Nil`, the non-recursive variant that signals the end of the list.
If we try to compile the code in Listing 15-3, we get the error shown in
Listing 15-4:
If we try to compile the code in [Listing 15-3][Listing-15-3], we get the error shown in
[Listing 15-4][Listing-15-4]:
[Listing-15-4]: #Listing-15-4
<a name="Listing-15-4"></a>
```text
error[E0072]: recursive type `List` has infinite size
@ -170,7 +182,7 @@ type.
#### Computing the Size of a Non-Recursive Type
Recall the `Message` enum we defined in Listing 6-2 when we discussed enum
Recall the `Message` enum we defined in [Listing 6-2][Listing-6-2] when we discussed enum
definitions in Chapter 6:
```rust
@ -190,13 +202,16 @@ used, the most space a `Message` value will need is the space it would take to
store the largest of its variants.
Contrast this with what happens when Rust tries to determine how much space a
recursive type like the `List` enum in Listing 15-2 needs. The compiler starts
recursive type like the `List` enum in [Listing 15-2][Listing-15-2] needs. The compiler starts
by looking at the `Cons` variant, which holds a value of type `i32` and a value
of type `List`. Therefore, `Cons` needs an amount of space equal to the size of
an `i32` plus the size of a `List`. To figure out how much memory the `List`
type needs, the compiler looks at the variants, starting with the `Cons`
variant. The `Cons` variant holds a value of type `i32` and a value of type
`List`, and this process continues infinitely, as shown in Figure 15-1.
`List`, and this process continues infinitely, as shown in [Figure 15-1][Figure-15-1].
[Figure-15-1]: #Figure-15-1
<a name="Figure-15-1"></a>
<img alt="An infinite Cons list" src="img/trpl15-01.svg" class="center" style="width: 50%;" />
@ -206,7 +221,7 @@ variant. The `Cons` variant holds a value of type `i32` and a value of type
#### Using `Box<T>` to Get a Recursive Type with a Known Size
Rust cant figure out how much space to allocate for recursively defined types,
so the compiler gives the error in Listing 15-4. But the error does include
so the compiler gives the error in [Listing 15-4][Listing-15-4]. But the error does include
this helpful suggestion:
```text
@ -227,11 +242,14 @@ Conceptually, we still have a list, created with lists “holding” other lists
but this implementation is now more like placing the items next to one another
rather than inside one another.
We can change the definition of the `List` enum in Listing 15-2 and the usage
of the `List` in Listing 15-3 to the code in Listing 15-5, which will compile:
We can change the definition of the `List` enum in [Listing 15-2][Listing-15-2] and the usage
of the `List` in [Listing 15-3][Listing-15-3] to the code in [Listing 15-5][Listing-15-5], which will compile:
<span class="filename">Filename: src/main.rs</span>
[Listing-15-5]: #Listing-15-5
<a name="Listing-15-5"></a>
```rust
enum List {
Cons(i32, Box<List>),
@ -256,9 +274,12 @@ boxs pointer data. The `Nil` variant stores no values, so it needs less space
than the `Cons` variant. We now know that any `List` value will take up the
size of an `i32` plus the size of a boxs pointer data. By using a box, weve
broken the infinite, recursive chain, so the compiler can figure out the size
it needs to store a `List` value. Figure 15-2 shows what the `Cons` variant
it needs to store a `List` value. [Figure 15-2][Figure-15-2] shows what the `Cons` variant
looks like now.
[Figure-15-2]: #Figure-15-2
<a name="Figure-15-2"></a>
<img alt="A finite Cons list" src="img/trpl15-02.svg" class="center" />
<span class="caption">Figure 15-2: A `List` that is not infinitely sized
@ -278,3 +299,12 @@ up as well because of the `Drop` trait implementation. Lets explore these two
traits in more detail. These two traits will be even more important to the
functionality provided by the other smart pointer types well discuss in the
rest of this chapter.
[Listing-15-1]: ch15-01-box.html#Listing-15-1
[Listing-15-2]: ch15-01-box.html#Listing-15-2
[Listing-15-3]: ch15-01-box.html#Listing-15-3
[Listing-15-4]: ch15-01-box.html#Listing-15-4
[Figure-15-1]: ch15-01-box.html#Figure-15-1
[Listing-15-5]: ch15-01-box.html#Listing-15-5
[Figure-15-2]: ch15-01-box.html#Figure-15-2
[Listing-6-2]: ch06-01-defining-an-enum.html#Listing-6-2

View File

@ -17,12 +17,15 @@ or smart pointers.
### Following the Pointer to the Value with the Dereference Operator
A regular reference is a type of pointer, and one way to think of a pointer is
as an arrow to a value stored somewhere else. In Listing 15-6, we create a
as an arrow to a value stored somewhere else. In [Listing 15-6][Listing-15-6], we create a
reference to an `i32` value and then use the dereference operator to follow the
reference to the data:
<span class="filename">Filename: src/main.rs</span>
[Listing-15-6]: #Listing-15-6
<a name="Listing-15-6"></a>
```rust
fn main() {
let x = 5;
@ -64,11 +67,14 @@ to the value its pointing to.
### Using `Box<T>` Like a Reference
We can rewrite the code in Listing 15-6 to use a `Box<T>` instead of a
reference; the dereference operator will work as shown in Listing 15-7:
We can rewrite the code in [Listing 15-6][Listing-15-6] to use a `Box<T>` instead of a
reference; the dereference operator will work as shown in [Listing 15-7][Listing-15-7]:
<span class="filename">Filename: src/main.rs</span>
[Listing-15-7]: #Listing-15-7
<a name="Listing-15-7"></a>
```rust
fn main() {
let x = 5;
@ -82,7 +88,7 @@ fn main() {
<span class="caption">Listing 15-7: Using the dereference operator on a
`Box<i32>`</span>
The only difference between Listing 15-7 and Listing 15-6 is that here we set
The only difference between [Listing 15-7][Listing-15-7] and [Listing 15-6][Listing-15-6] is that here we set
`y` to be an instance of a box pointing to the value in `x` rather than a
reference pointing to the value of `x`. In the last assertion, we can use the
dereference operator to follow the boxs pointer in the same way that we did
@ -97,11 +103,14 @@ references by default. Then well look at how to add the ability to use the
dereference operator.
The `Box<T>` type is ultimately defined as a tuple struct with one element, so
Listing 15-8 defines a `MyBox<T>` type in the same way. Well also define a
[Listing 15-8][Listing-15-8] defines a `MyBox<T>` type in the same way. Well also define a
`new` function to match the `new` function defined on `Box<T>`.
<span class="filename">Filename: src/main.rs</span>
[Listing-15-8]: #Listing-15-8
<a name="Listing-15-8"></a>
```rust
struct MyBox<T>(T);
@ -119,13 +128,16 @@ we want our type to hold values of any type. The `MyBox` type is a tuple struct
with one element of type `T`. The `MyBox::new` function takes one parameter of
type `T` and returns a `MyBox` instance that holds the value passed in.
Lets try adding the `main` function in Listing 15-7 to Listing 15-8 and
Lets try adding the `main` function in [Listing 15-7][Listing-15-7] to [Listing 15-8][Listing-15-8] and
changing it to use the `MyBox<T>` type weve defined instead of `Box<T>`. The
code in Listing 15-9 wont compile because Rust doesnt know how to dereference
code in [Listing 15-9][Listing-15-9] wont compile because Rust doesnt know how to dereference
`MyBox`.
<span class="filename">Filename: src/main.rs</span>
[Listing-15-9]: #Listing-15-9
<a name="Listing-15-9"></a>
```rust,ignore
fn main() {
let x = 5;
@ -158,11 +170,14 @@ implement the `Deref` trait.
As discussed in Chapter 10, to implement a trait, we need to provide
implementations for the traits required methods. The `Deref` trait, provided
by the standard library, requires us to implement one method named `deref` that
borrows `self` and returns a reference to the inner data. Listing 15-10
borrows `self` and returns a reference to the inner data. [Listing 15-10][Listing-15-10]
contains an implementation of `Deref` to add to the definition of `MyBox`:
<span class="filename">Filename: src/main.rs</span>
[Listing-15-10]: #Listing-15-10
<a name="Listing-15-10"></a>
```rust
use std::ops::Deref;
@ -185,7 +200,7 @@ more detail in Chapter 19.
We fill in the body of the `deref` method with `&self.0` so `deref` returns a
reference to the value we want to access with the `*` operator. The `main`
function in Listing 15-9 that calls `*` on the `MyBox<T>` value now compiles,
function in [Listing 15-9][Listing-15-9] that calls `*` on the `MyBox<T>` value now compiles,
and the assertions pass!
Without the `Deref` trait, the compiler can only dereference `&` references.
@ -193,7 +208,7 @@ The `deref` method gives the compiler the ability to take a value of any type
that implements `Deref` and call the `deref` method to get a `&` reference that
it knows how to dereference.
When we entered `*y` in Listing 15-9, behind the scenes Rust actually ran this
When we entered `*y` in [Listing 15-9][Listing-15-9], behind the scenes Rust actually ran this
code:
```rust,ignore
@ -217,7 +232,7 @@ Note that the `*` operator is replaced with a call to the `deref` method and
then a call to the `*` operator just once, each time we use a `*` in our code.
Because the substitution of the `*` operator does not recurse infinitely, we
end up with data of type `i32`, which matches the `5` in `assert_eq!` in
Listing 15-9.
[Listing 15-9][Listing-15-9].
### Implicit Deref Coercions with Functions and Methods
@ -236,12 +251,15 @@ with `&` and `*`. The deref coercion feature also lets us write more code that
can work for either references or smart pointers.
To see deref coercion in action, lets use the `MyBox<T>` type we defined in
Listing 15-8 as well as the implementation of `Deref` that we added in Listing
15-10. Listing 15-11 shows the definition of a function that has a string slice
[Listing 15-8][Listing-15-8] as well as the implementation of `Deref` that we added in [Listing 15-10][Listing-15-10].
[Listing 15-11][Listing-15-11] shows the definition of a function that has a string slice
parameter:
<span class="filename">Filename: src/main.rs</span>
[Listing-15-11]: #Listing-15-11
<a name="Listing-15-11"></a>
```rust
fn hello(name: &str) {
println!("Hello, {}!", name);
@ -253,10 +271,13 @@ fn hello(name: &str) {
We can call the `hello` function with a string slice as an argument, such as
`hello("Rust");` for example. Deref coercion makes it possible to call `hello`
with a reference to a value of type `MyBox<String>`, as shown in Listing 15-12:
with a reference to a value of type `MyBox<String>`, as shown in [Listing 15-12][Listing-15-12]:
<span class="filename">Filename: src/main.rs</span>
[Listing-15-12]: #Listing-15-12
<a name="Listing-15-12"></a>
```rust
# use std::ops::Deref;
#
@ -291,18 +312,21 @@ fn main() {
Here were calling the `hello` function with the argument `&m`, which is a
reference to a `MyBox<String>` value. Because we implemented the `Deref` trait
on `MyBox<T>` in Listing 15-10, Rust can turn `&MyBox<String>` into `&String`
on `MyBox<T>` in [Listing 15-10][Listing-15-10], Rust can turn `&MyBox<String>` into `&String`
by calling `deref`. The standard library provides an implementation of `Deref`
on `String` that returns a string slice, and this is in the API documentation
for `Deref`. Rust calls `deref` again to turn the `&String` into `&str`, which
matches the `hello` functions definition.
If Rust didnt implement deref coercion, we would have to write the code in
Listing 15-13 instead of the code in Listing 15-12 to call `hello` with a value
[Listing 15-13][Listing-15-13] instead of the code in [Listing 15-12][Listing-15-12] to call `hello` with a value
of type `&MyBox<String>`.
<span class="filename">Filename: src/main.rs</span>
[Listing-15-13]: #Listing-15-13
<a name="Listing-15-13"></a>
```rust
# use std::ops::Deref;
#
@ -375,3 +399,12 @@ Converting an immutable reference to a mutable reference would require that
there is only one immutable reference to that data, and the borrowing rules
dont guarantee that. Therefore, Rust cant make the assumption that converting
an immutable reference to a mutable reference is possible.
[Listing-15-6]: ch15-02-deref.html#Listing-15-6
[Listing-15-7]: ch15-02-deref.html#Listing-15-7
[Listing-15-8]: ch15-02-deref.html#Listing-15-8
[Listing-15-9]: ch15-02-deref.html#Listing-15-9
[Listing-15-10]: ch15-02-deref.html#Listing-15-10
[Listing-15-11]: ch15-02-deref.html#Listing-15-11
[Listing-15-12]: ch15-02-deref.html#Listing-15-12
[Listing-15-13]: ch15-02-deref.html#Listing-15-13

View File

@ -22,13 +22,16 @@ Specify the code to run when a value goes out of scope by implementing the
`drop` that takes a mutable reference to `self`. To see when Rust calls `drop`,
lets implement `drop` with `println!` statements for now.
Listing 15-14 shows a `CustomSmartPointer` struct whose only custom
[Listing 15-14][Listing-15-14] shows a `CustomSmartPointer` struct whose only custom
functionality is that it will print `Dropping CustomSmartPointer!` when the
instance goes out of scope. This example demonstrates when Rust runs the `drop`
function.
<span class="filename">Filename: src/main.rs</span>
[Listing-15-14]: #Listing-15-14
<a name="Listing-15-14"></a>
```rust
struct CustomSmartPointer {
data: String,
@ -90,11 +93,14 @@ you have to call the `std::mem::drop` function provided by the standard library
if you want to force a value to be dropped before the end of its scope.
If we try to call the `Drop` traits `drop` method manually by modifying the
`main` function from Listing 15-14, as shown in Listing 15-15, well get a
`main` function from [Listing 15-14][Listing-15-14], as shown in [Listing 15-15][Listing-15-15], well get a
compiler error:
<span class="filename">Filename: src/main.rs</span>
[Listing-15-15]: #Listing-15-15
<a name="Listing-15-15"></a>
```rust,ignore
fn main() {
let c = CustomSmartPointer { data: String::from("some data") };
@ -134,11 +140,14 @@ a value to be cleaned up early, we can use the `std::mem::drop` function.
The `std::mem::drop` function is different than the `drop` method in the `Drop`
trait. We call it by passing the value we want to force to be dropped early as
an argument. The function is in the prelude, so we can modify `main` in Listing
15-15 to call the `drop` function, as shown in Listing 15-16:
an argument. The function is in the prelude, so we can modify `main` in [Listing 15-15][Listing-15-15]
to call the `drop` function, as shown in [Listing 15-16][Listing-15-16]:
<span class="filename">Filename: src/main.rs</span>
[Listing-15-16]: #Listing-15-16
<a name="Listing-15-16"></a>
```rust
# struct CustomSmartPointer {
# data: String,
@ -187,3 +196,7 @@ the value is no longer being used.
Now that weve examined `Box<T>` and some of the characteristics of smart
pointers, lets look at a few other smart pointers defined in the standard
library.
[Listing-15-14]: ch15-03-drop.html#Listing-15-14
[Listing-15-15]: ch15-03-drop.html#Listing-15-15
[Listing-15-16]: ch15-03-drop.html#Listing-15-16

View File

@ -31,9 +31,12 @@ multithreaded programs.
### Using `Rc<T>` to Share Data
Lets return to our cons list example in Listing 15-5. Recall that we defined
Lets return to our cons list example in [Listing 15-5][Listing-15-5]. Recall that we defined
it using `Box<T>`. This time, well create two lists that both share ownership
of a third list. Conceptually, this looks similar to Figure 15-3:
of a third list. Conceptually, this looks similar to [Figure 15-3][Figure-15-3]:
[Figure-15-3]: #Figure-15-3
<a name="Figure-15-3"></a>
<img alt="Two lists that share ownership of a third list" src="img/trpl15-03.svg" class="center" />
@ -46,10 +49,13 @@ lists will then continue on to the first `a` list containing 5 and 10. In other
words, both lists will share the first list containing 5 and 10.
Trying to implement this scenario using our definition of `List` with `Box<T>`
wont work, as shown in Listing 15-17:
wont work, as shown in [Listing 15-17][Listing-15-17]:
<span class="filename">Filename: src/main.rs</span>
[Listing-15-17]: #Listing-15-17
<a name="Listing-15-17"></a>
```rust,ignore
enum List {
Cons(i32, Box<List>),
@ -97,7 +103,7 @@ least as long as the entire list. The borrow checker wouldnt let us compile
be dropped before `a` could take a reference to it.
Instead, well change our definition of `List` to use `Rc<T>` in place of
`Box<T>`, as shown in Listing 15-18. Each `Cons` variant will now hold a value
`Box<T>`, as shown in [Listing 15-18][Listing-15-18]. Each `Cons` variant will now hold a value
and an `Rc<T>` pointing to a `List`. When we create `b`, instead of taking
ownership of `a`, well clone the `Rc<List>` that `a` is holding, thereby
increasing the number of references from one to two and letting `a` and `b`
@ -109,6 +115,9 @@ it.
<span class="filename">Filename: src/main.rs</span>
[Listing-15-18]: #Listing-15-18
<a name="Listing-15-18"></a>
```rust
enum List {
Cons(i32, Rc<List>),
@ -147,14 +156,17 @@ code, we only need to consider the deep-copy clones and can disregard calls to
### Cloning an `Rc<T>` Increases the Reference Count
Lets change our working example in Listing 15-18 so we can see the reference
Lets change our working example in [Listing 15-18][Listing-15-18] so we can see the reference
counts changing as we create and drop references to the `Rc<List>` in `a`.
In Listing 15-19, well change `main` so it has an inner scope around list `c`;
In [Listing 15-19][Listing-15-19], well change `main` so it has an inner scope around list `c`;
then we can see how the reference count changes when `c` goes out of scope.
<span class="filename">Filename: src/main.rs</span>
[Listing-15-19]: #Listing-15-19
<a name="Listing-15-19"></a>
```rust
# enum List {
# Cons(i32, Rc<List>),
@ -215,3 +227,9 @@ and inconsistencies. But being able to mutate data is very useful! In the next
section, well discuss the interior mutability pattern and the `RefCell<T>`
type that you can use in conjunction with an `Rc<T>` to work with this
immutability restriction.
[Listing-15-5]: ch15-01-box.html#Listing-15-5
[Figure-15-3]: ch15-04-rc.html#Figure-15-3
[Listing-15-17]: ch15-04-rc.html#Listing-15-17
[Listing-15-18]: ch15-04-rc.html#Listing-15-18
[Listing-15-19]: ch15-04-rc.html#Listing-15-19

View File

@ -131,10 +131,13 @@ that use our library will be expected to provide the mechanism for sending the
messages: the application could put a message in the application, send an
email, send a text message, or something else. The library doesnt need to know
that detail. All it needs is something that implements a trait well provide
called `Messenger`. Listing 15-20 shows the library code:
called `Messenger`. [Listing 15-20][Listing-15-20] shows the library code:
<span class="filename">Filename: src/lib.rs</span>
[Listing-15-20]: #Listing-15-20
<a name="Listing-15-20"></a>
```rust
pub trait Messenger {
fn send(&self, msg: &str);
@ -190,11 +193,14 @@ We need a mock object that, instead of sending an email or text message when we
call `send`, will only keep track of the messages its told to send. We can
create a new instance of the mock object, create a `LimitTracker` that uses the
mock object, call the `set_value` method on `LimitTracker`, and then check that
the mock object has the messages we expect. Listing 15-21 shows an attempt to
the mock object has the messages we expect. [Listing 15-21][Listing-15-21] shows an attempt to
implement a mock object to do just that, but the borrow checker wont allow it:
<span class="filename">Filename: src/lib.rs</span>
[Listing-15-21]: #Listing-15-21
<a name="Listing-15-21"></a>
```rust
#[cfg(test)]
mod tests {
@ -269,11 +275,14 @@ definition (feel free to try and see what error message you get).
This is a situation in which interior mutability can help! Well store the
`sent_messages` within a `RefCell<T>`, and then the `send` message will be
able to modify `sent_messages` to store the messages weve seen. Listing 15-22
able to modify `sent_messages` to store the messages weve seen. [Listing 15-22][Listing-15-22]
shows what that looks like:
<span class="filename">Filename: src/lib.rs</span>
[Listing-15-22]: #Listing-15-22
<a name="Listing-15-22"></a>
```rust
#[cfg(test)]
mod tests {
@ -346,13 +355,16 @@ borrows or one mutable borrow at any point in time.
If we try to violate these rules, rather than getting a compiler error as we
would with references, the implementation of `RefCell<T>` will panic at
runtime. Listing 15-23 shows a modification of the implementation of `send` in
Listing 15-22. Were deliberately trying to create two mutable borrows active
runtime. [Listing 15-23][Listing-15-23] shows a modification of the implementation of `send` in
[Listing 15-22][Listing-15-22]. Were deliberately trying to create two mutable borrows active
for the same scope to illustrate that `RefCell<T>` prevents us from doing this
at runtime.
<span class="filename">Filename: src/lib.rs</span>
[Listing-15-23]: #Listing-15-23
<a name="Listing-15-23"></a>
```rust,ignore
impl Messenger for MockMessenger {
fn send(&self, message: &str) {
@ -371,8 +383,8 @@ same scope to see that `RefCell<T>` will panic</span>
We create a variable `one_borrow` for the `RefMut<T>` smart pointer returned
from `borrow_mut`. Then we create another mutable borrow in the same way in the
variable `two_borrow`. This makes two mutable references in the same scope,
which isnt allowed. When we run the tests for our library, the code in Listing
15-23 will compile without any errors, but the test will fail:
which isnt allowed. When we run the tests for our library, the code in [Listing 15-23][Listing-15-23]
will compile without any errors, but the test will fail:
```text
---- tests::it_sends_an_over_75_percent_warning_message stdout ----
@ -402,16 +414,19 @@ A common way to use `RefCell<T>` is in combination with `Rc<T>`. Recall that
access to that data. If you have an `Rc<T>` that holds a `RefCell<T>`, you can
get a value that can have multiple owners *and* that you can mutate!
For example, recall the cons list example in Listing 15-18 where we used
For example, recall the cons list example in [Listing 15-18][Listing-15-18] where we used
`Rc<T>` to allow multiple lists to share ownership of another list. Because
`Rc<T>` holds only immutable values, we cant change any of the values in the
list once weve created them. Lets add in `RefCell<T>` to gain the ability to
change the values in the lists. Listing 15-24 shows that by using a
change the values in the lists. [Listing 15-24][Listing-15-24] shows that by using a
`RefCell<T>` in the `Cons` definition, we can modify the value stored in all
the lists:
<span class="filename">Filename: src/main.rs</span>
[Listing-15-24]: #Listing-15-24
<a name="Listing-15-24"></a>
```rust
#[derive(Debug)]
enum List {
@ -450,7 +465,7 @@ than transferring ownership from `value` to `a` or having `a` borrow from
`value`.
We wrap the list `a` in an `Rc<T>` so when we create lists `b` and `c`, they
can both refer to `a`, which is what we did in Listing 15-18.
can both refer to `a`, which is what we did in [Listing 15-18][Listing-15-18].
After weve created the lists in `a`, `b`, and `c`, we add 10 to the value in
`value`. We do this by calling `borrow_mut` on `value`, which uses the
@ -481,3 +496,10 @@ inner value, the value is copied in and out of the `Cell<T>`. Theres also
`Mutex<T>`, which offers interior mutability thats safe to use across threads;
well discuss its use in Chapter 16. Check out the standard library docs for
more details on the differences between these types.
[Listing-15-20]: ch15-05-interior-mutability.html#Listing-15-20
[Listing-15-21]: ch15-05-interior-mutability.html#Listing-15-21
[Listing-15-22]: ch15-05-interior-mutability.html#Listing-15-22
[Listing-15-23]: ch15-05-interior-mutability.html#Listing-15-23
[Listing-15-24]: ch15-05-interior-mutability.html#Listing-15-24
[Listing-15-18]: ch15-04-rc.html#Listing-15-18

View File

@ -12,14 +12,16 @@ item in the cycle will never reach 0, and the values will never be dropped.
### Creating a Reference Cycle
Lets look at how a reference cycle might happen and how to prevent it,
starting with the definition of the `List` enum and a `tail` method in Listing
15-25:
starting with the definition of the `List` enum and a `tail` method in [Listing 15-25][Listing-15-25]:
<span class="filename">Filename: src/main.rs</span>
<!-- Hidden fn main is here to disable the automatic wrapping in fn main that
doc tests do; the `use List` fails if this listing is put within a main -->
[Listing-15-25]: #Listing-15-25
<a name="Listing-15-25"></a>
```rust
# fn main() {}
use std::rc::Rc;
@ -45,21 +47,24 @@ impl List {
<span class="caption">Listing 15-25: A cons list definition that holds a
`RefCell<T>` so we can modify what a `Cons` variant is referring to</span>
Were using another variation of the `List` definition in Listing 15-5. The
Were using another variation of the `List` definition in [Listing 15-5][Listing-15-5]. The
second element in the `Cons` variant is now `RefCell<Rc<List>>`, meaning that
instead of having the ability to modify the `i32` value as we did in Listing
15-24, we want to modify which `List` value a `Cons` variant is pointing to.
instead of having the ability to modify the `i32` value as we did in [Listing 15-24][Listing-15-24],
we want to modify which `List` value a `Cons` variant is pointing to.
Were also adding a `tail` method to make it convenient for us to access the
second item if we have a `Cons` variant.
In Listing 15-26, were adding a `main` function that uses the definitions in
Listing 15-25. This code creates a list in `a` and a list in `b` that points to
In [Listing 15-26][Listing-15-26], were adding a `main` function that uses the definitions in
[Listing 15-25][Listing-15-25]. This code creates a list in `a` and a list in `b` that points to
the list in `a`. Then it modifies the list in `a` to point to `b`, creating a
reference cycle. There are `println!` statements along the way to show what the
reference counts are at various points in this process.
<span class="filename">Filename: src/main.rs</span>
[Listing-15-26]: #Listing-15-26
<a name="Listing-15-26"></a>
```rust
# use List::{Cons, Nil};
# use std::rc::Rc;
@ -139,8 +144,10 @@ will try to drop `b` first, which will decrease the count in each of the
However, because `a` is still referencing the `Rc<List>` that was in `b`, that
`Rc<List>` has a count of 1 rather than 0, so the memory the `Rc<List>` has on
the heap wont be dropped. The memory will just sit there with a count of 1,
forever. To visualize this reference cycle, weve created a diagram in Figure
15-4.
forever. To visualize this reference cycle, weve created a diagram in [Figure 15-4][Figure-15-4].
[Figure-15-4]: #Figure-15-4
<a name="Figure-15-4"></a>
<img alt="Reference cycle of lists" src="img/trpl15-04.svg" class="center" />
@ -169,7 +176,7 @@ Another solution for avoiding reference cycles is reorganizing your data
structures so that some references express ownership and some references dont.
As a result, you can have cycles made up of some ownership relationships and
some non-ownership relationships, and only the ownership relationships affect
whether or not a value can be dropped. In Listing 15-25, we always want `Cons`
whether or not a value can be dropped. In [Listing 15-25][Listing-15-25], we always want `Cons`
variants to own their list, so reorganizing the data structure isnt possible.
Lets look at an example using graphs made up of parent nodes and child nodes
to see when non-ownership relationships are an appropriate way to prevent
@ -233,10 +240,13 @@ modify which nodes are children of another node, so we have a `RefCell<T>` in
Next, well use our struct definition and create one `Node` instance named
`leaf` with the value 3 and no children, and another instance named `branch`
with the value 5 and `leaf` as one of its children, as shown in Listing 15-27:
with the value 5 and `leaf` as one of its children, as shown in [Listing 15-27][Listing-15-27]:
<span class="filename">Filename: src/main.rs</span>
[Listing-15-27]: #Listing-15-27
<a name="Listing-15-27"></a>
```rust
# use std::rc::Rc;
# use std::cell::RefCell;
@ -303,11 +313,14 @@ struct Node {
```
A node will be able to refer to its parent node but doesnt own its parent.
In Listing 15-28, we update `main` to use this new definition so the `leaf`
In [Listing 15-28][Listing-15-28], we update `main` to use this new definition so the `leaf`
node will have a way to refer to its parent, `branch`:
<span class="filename">Filename: src/main.rs</span>
[Listing-15-28]: #Listing-15-28
<a name="Listing-15-28"></a>
```rust
# use std::rc::{Rc, Weak};
# use std::cell::RefCell;
@ -344,7 +357,7 @@ fn main() {
parent node `branch`</span>
Creating the `leaf` node looks similar to how creating the `leaf` node looked
in Listing 15-27 with the exception of the `parent` field: `leaf` starts out
in [Listing 15-27][Listing-15-27] with the exception of the `parent` field: `leaf` starts out
without a parent, so we create a new, empty `Weak<Node>` reference instance.
At this point, when we try to get a reference to the parent of `leaf` by using
@ -367,7 +380,7 @@ the `Rc<Node>` in `branch.`
When we print the parent of `leaf` again, this time well get a `Some` variant
holding `branch`: now `leaf` can access its parent! When we print `leaf`, we
also avoid the cycle that eventually ended in a stack overflow like we had in
Listing 15-26; the `Weak<Node>` references are printed as `(Weak)`:
[Listing 15-26][Listing-15-26]; the `Weak<Node>` references are printed as `(Weak)`:
```text
leaf parent = Some(Node { value: 5, parent: RefCell { value: (Weak) },
@ -385,10 +398,13 @@ Lets look at how the `strong_count` and `weak_count` values of the `Rc<Node>`
instances change by creating a new inner scope and moving the creation of
`branch` into that scope. By doing so, we can see what happens when `branch` is
created and then dropped when it goes out of scope. The modifications are shown
in Listing 15-29:
in [Listing 15-29][Listing-15-29]:
<span class="filename">Filename: src/main.rs</span>
[Listing-15-29]: #Listing-15-29
<a name="Listing-15-29"></a>
```rust
# use std::rc::{Rc, Weak};
# use std::cell::RefCell;
@ -496,3 +512,12 @@ information.
Next, well talk about concurrency in Rust. Youll even learn about a few new
smart pointers.
[Listing-15-24]: ch15-05-interior-mutability.html#Listing-15-24
[Listing-15-5]: ch15-01-box.html#Listing-15-5
[Listing-15-25]: ch15-06-reference-cycles.html#Listing-15-25
[Listing-15-26]: ch15-06-reference-cycles.html#Listing-15-26
[Figure-15-4]: ch15-06-reference-cycles.html#Figure-15-4
[Listing-15-27]: ch15-06-reference-cycles.html#Listing-15-27
[Listing-15-28]: ch15-06-reference-cycles.html#Listing-15-28
[Listing-15-29]: ch15-06-reference-cycles.html#Listing-15-29

View File

@ -65,11 +65,14 @@ thread-related API provided by the standard library.
To create a new thread, we call the `thread::spawn` function and pass it a
closure (we talked about closures in Chapter 13) containing the code we want to
run in the new thread. The example in Listing 16-1 prints some text from a main
run in the new thread. The example in [Listing 16-1][Listing-16-1] prints some text from a main
thread and other text from a new thread:
<span class="filename">Filename: src/main.rs</span>
[Listing-16-1]: #Listing-16-1
<a name="Listing-16-1"></a>
```rust
use std::thread;
use std::time::Duration;
@ -123,7 +126,7 @@ for the operating system to switch between the threads.
### Waiting for All Threads to Finish Using `join` Handles
The code in Listing 16-1 not only stops the spawned thread prematurely most of
The code in [Listing 16-1][Listing-16-1] not only stops the spawned thread prematurely most of
the time due to the main thread ending, but also cant guarantee that the
spawned thread will get to run at all. The reason is that there is no guarantee
on the order in which threads run!
@ -132,12 +135,15 @@ We can fix the problem of the spawned thread not getting to run, or not getting
to run completely, by saving the return value of `thread::spawn` in a variable.
The return type of `thread::spawn` is `JoinHandle`. A `JoinHandle` is an owned
value that, when we call the `join` method on it, will wait for its thread to
finish. Listing 16-2 shows how to use the `JoinHandle` of the thread we created
in Listing 16-1 and call `join` to make sure the spawned thread finishes before
finish. [Listing 16-2][Listing-16-2] shows how to use the `JoinHandle` of the thread we created
in [Listing 16-1][Listing-16-1] and call `join` to make sure the spawned thread finishes before
`main` exits:
<span class="filename">Filename: src/main.rs</span>
[Listing-16-2]: #Listing-16-2
<a name="Listing-16-2"></a>
```rust
use std::thread;
use std::time::Duration;
@ -165,7 +171,7 @@ to guarantee the thread is run to completion</span>
Calling `join` on the handle blocks the thread currently running until the
thread represented by the handle terminates. *Blocking* a thread means that
thread is prevented from performing work or exiting. Because weve put the call
to `join` after the main threads `for` loop, running Listing 16-2 should
to `join` after the main threads `for` loop, running [Listing 16-2][Listing-16-2] should
produce output similar to this:
```text
@ -245,15 +251,18 @@ list of a closure to force the closure to take ownership of the values it uses
in the environment. This technique is especially useful when creating new
threads in order to transfer ownership of values from one thread to another.
Notice in Listing 16-1 that the closure we pass to `thread::spawn` takes no
Notice in [Listing 16-1][Listing-16-1] that the closure we pass to `thread::spawn` takes no
arguments: were not using any data from the main thread in the spawned
threads code. To use data from the main thread in the spawned thread, the
spawned threads closure must capture the values it needs. Listing 16-3 shows
spawned threads closure must capture the values it needs. [Listing 16-3][Listing-16-3] shows
an attempt to create a vector in the main thread and use it in the spawned
thread. However, this wont yet work, as youll see in a moment.
<span class="filename">Filename: src/main.rs</span>
[Listing-16-3]: #Listing-16-3
<a name="Listing-16-3"></a>
```rust,ignore
use std::thread;
@ -298,11 +307,14 @@ to `v`, the closure tries to borrow `v`. However, theres a problem: Rust can
tell how long the spawned thread will run, so it doesnt know if the reference
to `v` will always be valid.
Listing 16-4 provides a scenario thats more likely to have a reference to `v`
[Listing 16-4][Listing-16-4] provides a scenario thats more likely to have a reference to `v`
that wont be valid:
<span class="filename">Filename: src/main.rs</span>
[Listing-16-4]: #Listing-16-4
<a name="Listing-16-4"></a>
```rust,ignore
use std::thread;
@ -329,7 +341,7 @@ thread has a reference to `v` inside, but the main thread immediately drops
spawned thread starts to execute, `v` is no longer valid, so a reference to it
is also invalid. Oh no!
To fix the compiler error in Listing 16-3, we can use the error messages
To fix the compiler error in [Listing 16-3][Listing-16-3], we can use the error messages
advice:
```text
@ -342,11 +354,14 @@ variables), use the `move` keyword
By adding the `move` keyword before the closure, we force the closure to take
ownership of the values its using rather than allowing Rust to infer that it
should borrow the values. The modification to Listing 16-3 shown in Listing
16-5 will compile and run as we intend:
should borrow the values. The modification to [Listing 16-3][Listing-16-3] shown in [Listing 16-5][Listing-16-5]
will compile and run as we intend:
<span class="filename">Filename: src/main.rs</span>
[Listing-16-5]: #Listing-16-5
<a name="Listing-16-5"></a>
```rust
use std::thread;
@ -364,9 +379,9 @@ fn main() {
<span class="caption">Listing 16-5: Using the `move` keyword to force a closure
to take ownership of the values it uses</span>
What would happen to the code in Listing 16-4 where the main thread called
What would happen to the code in [Listing 16-4][Listing-16-4] where the main thread called
`drop` if we use a `move` closure? Would `move` fix that case? Unfortunately,
no; we would get a different error because what Listing 16-4 is trying to do
no; we would get a different error because what [Listing 16-4][Listing-16-4] is trying to do
isnt allowed for a different reason. If we added `move` to the closure, we
would move `v` into the closures environment, and we could no longer call
`drop` on it in the main thread. We would get this compiler error instead:
@ -386,14 +401,20 @@ error[E0382]: use of moved value: `v`
```
Rusts ownership rules have saved us again! We got an error from the code in
Listing 16-3 because Rust was being conservative and only borrowing `v` for the
[Listing 16-3][Listing-16-3] because Rust was being conservative and only borrowing `v` for the
thread, which meant the main thread could theoretically invalidate the spawned
threads reference. By telling Rust to move ownership of `v` to the spawned
thread, were guaranteeing Rust that the main thread wont use `v` anymore. If
we change Listing 16-4 in the same way, were then violating the ownership
we change [Listing 16-4][Listing-16-4] in the same way, were then violating the ownership
rules when we try to use `v` in the main thread. The `move` keyword overrides
Rusts conservative default of borrowing; it doesnt let us violate the
ownership rules.
With a basic understanding of threads and the thread API, lets look at what we
can *do* with threads.
[Listing-16-1]: ch16-01-threads.html#Listing-16-1
[Listing-16-2]: ch16-01-threads.html#Listing-16-2
[Listing-16-3]: ch16-01-threads.html#Listing-16-3
[Listing-16-4]: ch16-01-threads.html#Listing-16-4
[Listing-16-5]: ch16-01-threads.html#Listing-16-5

View File

@ -29,12 +29,15 @@ use channels to implement a chat system or a system where many threads perform
parts of a calculation and send the parts to one thread that aggregates the
results.
First, in Listing 16-6, well create a channel but not do anything with it.
First, in [Listing 16-6][Listing-16-6], well create a channel but not do anything with it.
Note that this wont compile yet because Rust cant tell what type of values we
want to send over the channel.
<span class="filename">Filename: src/main.rs</span>
[Listing-16-6]: #Listing-16-6
<a name="Listing-16-6"></a>
```rust
use std::sync::mpsc;
@ -69,11 +72,14 @@ extract the pieces of the tuple returned by `mpsc::channel`.
Lets move the transmitting end into a spawned thread and have it send one
string so the spawned thread is communicating with the main thread, as shown in
Listing 16-7. This is like putting a rubber duck in the river upstream or
[Listing 16-7][Listing-16-7]. This is like putting a rubber duck in the river upstream or
sending a chat message from one thread to another.
<span class="filename">Filename: src/main.rs</span>
[Listing-16-7]: #Listing-16-7
<a name="Listing-16-7"></a>
```rust
use std::thread;
use std::sync::mpsc;
@ -103,12 +109,15 @@ will return an error. In this example, were calling `unwrap` to panic in case
of an error. But in a real application, we would handle it properly: return to
Chapter 9 to review strategies for proper error handling.
In Listing 16-8, well get the value from the receiving end of the channel in
In [Listing 16-8][Listing-16-8], well get the value from the receiving end of the channel in
the main thread. This is like retrieving the rubber duck from the water at the
end of the river or like getting a chat message.
<span class="filename">Filename: src/main.rs</span>
[Listing-16-8]: #Listing-16-8
<a name="Listing-16-8"></a>
```rust
use std::thread;
use std::sync::mpsc;
@ -148,7 +157,7 @@ Weve used `recv` in this example for simplicity; we dont have any other wo
for the main thread to do other than wait for messages, so blocking the main
thread is appropriate.
When we run the code in Listing 16-8, well see the value printed from the main
When we run the code in [Listing 16-8][Listing-16-8], well see the value printed from the main
thread:
```text
@ -164,11 +173,14 @@ write safe, concurrent code. Preventing errors in concurrent programming is the
advantage of thinking about ownership throughout your Rust programs. Lets do
an experiment to show how channels and ownership work together to prevent
problems: well try to use a `val` value in the spawned thread *after* weve
sent it down the channel. Try compiling the code in Listing 16-9 to see why
sent it down the channel. Try compiling the code in [Listing 16-9][Listing-16-9] to see why
this code isnt allowed:
<span class="filename">Filename: src/main.rs</span>
[Listing-16-9]: #Listing-16-9
<a name="Listing-16-9"></a>
```rust,ignore
use std::thread;
use std::sync::mpsc;
@ -195,7 +207,7 @@ Allowing this would be a bad idea: once the value has been sent to another
thread, that thread could modify or drop it before we try to use the value
again. Potentially, the other threads modifications could cause errors or
unexpected results due to inconsistent or nonexistent data. However, Rust gives
us an error if we try to compile the code in Listing 16-9:
us an error if we try to compile the code in [Listing 16-9][Listing-16-9]:
```text
error[E0382]: use of moved value: `val`
@ -217,14 +229,17 @@ after sending it; the ownership system checks that everything is okay.
### Sending Multiple Values and Seeing the Receiver Waiting
The code in Listing 16-8 compiled and ran, but it didnt clearly show us that
two separate threads were talking to each other over the channel. In Listing
16-10 weve made some modifications that will prove the code in Listing 16-8 is
The code in [Listing 16-8][Listing-16-8] compiled and ran, but it didnt clearly show us that
two separate threads were talking to each other over the channel. In [Listing 16-10][Listing-16-10]
weve made some modifications that will prove the code in [Listing 16-8][Listing-16-8] is
running concurrently: the spawned thread will now send multiple messages and
pause for a second between each message.
<span class="filename">Filename: src/main.rs</span>
[Listing-16-10]: #Listing-16-10
<a name="Listing-16-10"></a>
```rust
use std::thread;
use std::sync::mpsc;
@ -265,7 +280,7 @@ In the main thread, were not calling the `recv` function explicitly anymore:
instead, were treating `rx` as an iterator. For each value received, were
printing it. When the channel is closed, iteration will end.
When running the code in Listing 16-10, you should see the following output
When running the code in [Listing 16-10][Listing-16-10], you should see the following output
with a 1-second pause in between each line:
```text
@ -282,12 +297,15 @@ the spawned thread.
### Creating Multiple Producers by Cloning the Transmitter
Earlier we mentioned that `mpsc` was an acronym for *multiple producer,
single consumer*. Lets put `mpsc` to use and expand the code in Listing 16-10
single consumer*. Lets put `mpsc` to use and expand the code in [Listing 16-10][Listing-16-10]
to create multiple threads that all send values to the same receiver. We can do
so by cloning the transmitting half of the channel, as shown in Listing 16-11:
so by cloning the transmitting half of the channel, as shown in [Listing 16-11][Listing-16-11]:
<span class="filename">Filename: src/main.rs</span>
[Listing-16-11]: #Listing-16-11
<a name="Listing-16-11"></a>
```rust
# use std::thread;
# use std::sync::mpsc;
@ -364,3 +382,10 @@ will be more nondeterministic and create different output each time.
Now that weve looked at how channels work, lets look at a different method of
concurrency.
[Listing-16-6]: ch16-02-message-passing.html#Listing-16-6
[Listing-16-7]: ch16-02-message-passing.html#Listing-16-7
[Listing-16-8]: ch16-02-message-passing.html#Listing-16-8
[Listing-16-9]: ch16-02-message-passing.html#Listing-16-9
[Listing-16-10]: ch16-02-message-passing.html#Listing-16-10
[Listing-16-11]: ch16-02-message-passing.html#Listing-16-11

View File

@ -49,10 +49,13 @@ system and ownership rules, you cant get locking and unlocking wrong.
#### The API of `Mutex<T>`
As an example of how to use a mutex, lets start by using a mutex in a
single-threaded context, as shown in Listing 16-12:
single-threaded context, as shown in [Listing 16-12][Listing-16-12]:
<span class="filename">Filename: src/main.rs</span>
[Listing-16-12]: #Listing-16-12
<a name="Listing-16-12"></a>
```rust
use std::sync::Mutex;
@ -90,8 +93,8 @@ As you might suspect, `Mutex<T>` is a smart pointer. More accurately, the call
to `lock` *returns* a smart pointer called `MutexGuard`. This smart pointer
implements `Deref` to point at our inner data; the smart pointer also has a
`Drop` implementation that releases the lock automatically when a `MutexGuard`
goes out of scope, which happens at the end of the inner scope in Listing
16-12. As a result, we dont risk forgetting to release the lock and blocking
goes out of scope, which happens at the end of the inner scope in [Listing 16-12][Listing-16-12].
As a result, we dont risk forgetting to release the lock and blocking
the mutex from being used by other threads because the lock release happens
automatically.
@ -104,11 +107,14 @@ Now, lets try to share a value between multiple threads using `Mutex<T>`.
Well spin up 10 threads and have them each increment a counter value by 1, so
the counter goes from 0 to 10. Note that the next few examples will have
compiler errors, and well use those errors to learn more about using
`Mutex<T>` and how Rust helps us use it correctly. Listing 16-13 has our
`Mutex<T>` and how Rust helps us use it correctly. [Listing 16-13][Listing-16-13] has our
starting example:
<span class="filename">Filename: src/main.rs</span>
[Listing-16-13]: #Listing-16-13
<a name="Listing-16-13"></a>
```rust,ignore
use std::sync::Mutex;
use std::thread;
@ -138,15 +144,15 @@ fn main() {
guarded by a `Mutex<T>`</span>
We create a `counter` variable to hold an `i32` inside a `Mutex<T>`, as we
did in Listing 16-12. Next, we create 10 threads by iterating over a range
did in [Listing 16-12][Listing-16-12]. Next, we create 10 threads by iterating over a range
of numbers. We use `thread::spawn` and give all the threads the same closure,
one that moves the counter into the thread, acquires a lock on the `Mutex<T>`
by calling the `lock` method, and then adds 1 to the value in the mutex. When a
thread finishes running its closure, `num` will go out of scope and release the
lock so another thread can acquire it.
In the main thread, we collect all the join handles. Then, as we did in Listing
16-2, we call `join` on each handle to make sure all the threads finish. At
In the main thread, we collect all the join handles. Then, as we did in [Listing 16-2][Listing-16-2],
we call `join` on each handle to make sure all the threads finish. At
that point, the main thread will acquire the lock and print the result of this
program.
@ -185,7 +191,7 @@ but its not allowed!
Lets figure this out by simplifying the program. Instead of making 10 threads
in a `for` loop, lets just make two threads without a loop and see what
happens. Replace the first `for` loop in Listing 16-13 with this code instead:
happens. Replace the first `for` loop in [Listing 16-13][Listing-16-13] with this code instead:
```rust,ignore
use std::sync::Mutex;
@ -262,13 +268,16 @@ method we discussed in Chapter 15.
In Chapter 15, we gave a value multiple owners by using the smart pointer
`Rc<T>` to create a reference counted value. Lets do the same here and see
what happens. Well wrap the `Mutex<T>` in `Rc<T>` in Listing 16-14 and clone
what happens. Well wrap the `Mutex<T>` in `Rc<T>` in [Listing 16-14][Listing-16-14] and clone
the `Rc<T>` before moving ownership to the thread. Now that weve seen the
errors, well also switch back to using the `for` loop, and well keep the
`move` keyword with the closure.
<span class="filename">Filename: src/main.rs</span>
[Listing-16-14]: #Listing-16-14
<a name="Listing-16-14"></a>
```rust,ignore
use std::rc::Rc;
use std::sync::Mutex;
@ -356,10 +365,13 @@ guarantees atomics provide.
Lets return to our example: `Arc<T>` and `Rc<T>` have the same API, so we fix
our program by changing the `use` line, the call to `new`, and the call to
`clone`. The code in Listing 16-15 will finally compile and run:
`clone`. The code in [Listing 16-15][Listing-16-15] will finally compile and run:
<span class="filename">Filename: src/main.rs</span>
[Listing-16-15]: #Listing-16-15
<a name="Listing-16-15"></a>
```rust
use std::sync::{Mutex, Arc};
use std::thread;
@ -424,3 +436,9 @@ useful information.
Well round out this chapter by talking about the `Send` and `Sync` traits and
how we can use them with custom types.
[Listing-16-2]: ch16-01-threads.html#Listing-16-2
[Listing-16-12]: ch16-03-shared-state.html#Listing-16-12
[Listing-16-13]: ch16-03-shared-state.html#Listing-16-13
[Listing-16-14]: ch16-03-shared-state.html#Listing-16-14
[Listing-16-15]: ch16-03-shared-state.html#Listing-16-15

View File

@ -21,7 +21,7 @@ where you dont want to pay the thread-safe performance penalty.
Therefore, Rusts type system and trait bounds ensure that you can never
accidentally send an `Rc<T>` value across threads unsafely. When we tried to do
this in Listing 16-14, we got the error `the trait Send is not implemented for
this in [Listing 16-14][Listing-16-14], we got the error `the trait Send is not implemented for
Rc<Mutex<i32>>`. When we switched to `Arc<T>`, which is `Send`, the code
compiled.
@ -85,3 +85,5 @@ go forth and make your programs concurrent, fearlessly!
Next, well talk about idiomatic ways to model problems and structure solutions
as your Rust programs get bigger. In addition, well discuss how Rusts idioms
relate to those you might be familiar with from object-oriented programming.
[Listing-16-14]: ch16-03-shared-state.html#Listing-16-14

View File

@ -41,11 +41,14 @@ can define a struct `AveragedCollection` that has a field containing a vector
of `i32` values. The struct can also have a field that contains the average of
the values in the vector, meaning the average doesnt have to be computed
on demand whenever anyone needs it. In other words, `AveragedCollection` will
cache the calculated average for us. Listing 17-1 has the definition of the
cache the calculated average for us. [Listing 17-1][Listing-17-1] has the definition of the
`AveragedCollection` struct:
<span class="filename">Filename: src/lib.rs</span>
[Listing-17-1]: #Listing-17-1
<a name="Listing-17-1"></a>
```rust
pub struct AveragedCollection {
list: Vec<i32>,
@ -61,10 +64,13 @@ The struct is marked `pub` so that other code can use it, but the fields within
the struct remain private. This is important in this case because we want to
ensure that whenever a value is added or removed from the list, the average is
also updated. We do this by implementing `add`, `remove`, and `average` methods
on the struct, as shown in Listing 17-2:
on the struct, as shown in [Listing 17-2][Listing-17-2]:
<span class="filename">Filename: src/lib.rs</span>
[Listing-17-2]: #Listing-17-2
<a name="Listing-17-2"></a>
```rust
# pub struct AveragedCollection {
# list: Vec<i32>,
@ -142,7 +148,7 @@ depending on your reason for reaching for inheritance in the first place.
You choose inheritance for two main reasons. One is for reuse of code: you can
implement particular behavior for one type, and inheritance enables you to
reuse that implementation for a different type. You can share Rust code using
default trait method implementations instead, which you saw in Listing 10-14
default trait method implementations instead, which you saw in [Listing 10-14][Listing-10-14]
when we added a default implementation of the `summarize` method on the
`Summary` trait. Any type implementing the `Summary` trait would have the
`summarize` method available on it without any further code. This is similar to
@ -179,3 +185,7 @@ design.
For these reasons, Rust takes a different approach, using trait objects instead
of inheritance. Lets look at how trait objects enable polymorphism in Rust.
[Listing-17-1]: ch17-01-what-is-oo.html#Listing-17-1
[Listing-17-2]: ch17-01-what-is-oo.html#Listing-17-2
[Listing-10-14]: ch10-02-traits.html#Listing-10-14

View File

@ -1,7 +1,7 @@
## Using Trait Objects that Allow for Values of Different Types
In Chapter 8, we mentioned that one limitation of vectors is that they can
store elements of only one type. We created a workaround in Listing 8-10 where
store elements of only one type. We created a workaround in [Listing 8-10][Listing-8-10] where
we defined a `SpreadsheetCell` enum that had variants to hold integers, floats,
and text. This meant we could store different types of data in each cell and
still have a vector that represented a row of cells. This is a perfectly good
@ -63,11 +63,14 @@ a trait object. Trait objects arent as generally useful as objects in other
languages: their specific purpose is to allow abstraction across common
behavior.
Listing 17-3 shows how to define a trait named `Draw` with one method named
[Listing 17-3][Listing-17-3] shows how to define a trait named `Draw` with one method named
`draw`:
<span class="filename">Filename: src/lib.rs</span>
[Listing-17-3]: #Listing-17-3
<a name="Listing-17-3"></a>
```rust
pub trait Draw {
fn draw(&self);
@ -77,13 +80,16 @@ pub trait Draw {
<span class="caption">Listing 17-3: Definition of the `Draw` trait</span>
This syntax should look familiar from our discussions on how to define traits
in Chapter 10. Next comes some new syntax: Listing 17-4 defines a struct named
in Chapter 10. Next comes some new syntax: [Listing 17-4][Listing-17-4] defines a struct named
`Screen` that holds a vector named `components`. This vector is of type
`Box<Draw>`, which is a trait object; its a stand-in for any type inside a
`Box` that implements the `Draw` trait.
<span class="filename">Filename: src/lib.rs</span>
[Listing-17-4]: #Listing-17-4
<a name="Listing-17-4"></a>
```rust
# pub trait Draw {
# fn draw(&self);
@ -99,10 +105,13 @@ pub struct Screen {
trait</span>
On the `Screen` struct, well define a method named `run` that will call the
`draw` method on each of its `components`, as shown in Listing 17-5:
`draw` method on each of its `components`, as shown in [Listing 17-5][Listing-17-5]:
<span class="filename">Filename: src/lib.rs</span>
[Listing-17-5]: #Listing-17-5
<a name="Listing-17-5"></a>
```rust
# pub trait Draw {
# fn draw(&self);
@ -129,10 +138,13 @@ parameter with trait bounds. A generic type parameter can only be substituted
with one concrete type at a time, whereas trait objects allow for multiple
concrete types to fill in for the trait object at runtime. For example, we
could have defined the `Screen` struct using a generic type and a trait bound
as in Listing 17-6:
as in [Listing 17-6][Listing-17-6]:
<span class="filename">Filename: src/lib.rs</span>
[Listing-17-6]: #Listing-17-6
<a name="Listing-17-6"></a>
```rust
# pub trait Draw {
# fn draw(&self);
@ -171,10 +183,13 @@ Now well add some types that implement the `Draw` trait. Well provide the
`Button` type. Again, actually implementing a GUI library is beyond the scope
of this book, so the `draw` method wont have any useful implementation in its
body. To imagine what the implementation might look like, a `Button` struct
might have fields for `width`, `height`, and `label`, as shown in Listing 17-7:
might have fields for `width`, `height`, and `label`, as shown in [Listing 17-7][Listing-17-7]:
<span class="filename">Filename: src/lib.rs</span>
[Listing-17-7]: #Listing-17-7
<a name="Listing-17-7"></a>
```rust
# pub trait Draw {
# fn draw(&self);
@ -208,10 +223,13 @@ methods wont apply to types like `TextField`.
If someone using our library decides to implement a `SelectBox` struct that has
`width`, `height`, and `options` fields, they implement the `Draw` trait on the
`SelectBox` type as well, as shown in Listing 17-8:
`SelectBox` type as well, as shown in [Listing 17-8][Listing-17-8]:
<span class="filename">Filename: src/main.rs</span>
[Listing-17-8]: #Listing-17-8
<a name="Listing-17-8"></a>
```rust,ignore
extern crate gui;
use gui::Draw;
@ -236,10 +254,13 @@ Our librarys user can now write their `main` function to create a `Screen`
instance. To the `Screen` instance, they can add a `SelectBox` and a `Button`
by putting each in a `Box<T>` to become a trait object. They can then call the
`run` method on the `Screen` instance, which will call `draw` on each of the
components. Listing 17-9 shows this implementation:
components. [Listing 17-9][Listing-17-9] shows this implementation:
<span class="filename">Filename: src/main.rs</span>
[Listing-17-9]: #Listing-17-9
<a name="Listing-17-9"></a>
```rust,ignore
use gui::{Screen, Button};
@ -278,8 +299,8 @@ means it implements the `draw` method.
This concept—of being concerned only with the messages a value responds to
rather than the values concrete type—is similar to the concept *duck typing*
in dynamically typed languages: if it walks like a duck and quacks like a duck,
then it must be a duck! In the implementation of `run` on `Screen` in Listing
17-5, `run` doesnt need to know what the concrete type of each component is.
then it must be a duck! In the implementation of `run` on `Screen` in [Listing 17-5][Listing-17-5],
`run` doesnt need to know what the concrete type of each component is.
It doesnt check whether a component is an instance of a `Button` or a
`SelectBox`, it just calls the `draw` method on the component. By specifying
`Box<Draw>` as the type of the values in the `components` vector, weve defined
@ -291,11 +312,14 @@ value implements a particular method at runtime or worry about getting errors
if a value doesnt implement a method but we call it anyway. Rust wont compile
our code if the values dont implement the traits that the trait objects need.
For example, Listing 17-10 shows what happens if we try to create a `Screen`
For example, [Listing 17-10][Listing-17-10] shows what happens if we try to create a `Screen`
with a `String` as a component:
<span class="filename">Filename: src/main.rs</span>
[Listing-17-10]: #Listing-17-10
<a name="Listing-17-10"></a>
```rust,ignore
extern crate gui;
use gui::Screen;
@ -352,7 +376,7 @@ which method to call. There is a runtime cost when this lookup happens that
doesnt occur with static dispatch. Dynamic dispatch also prevents the compiler
from choosing to inline a methods code, which in turn prevents some
optimizations. However, we did get extra flexibility in the code that we wrote
in Listing 17-5 and were able to support in Listing 17-9, so its a trade-off
in [Listing 17-5][Listing-17-5] and were able to support in [Listing 17-9][Listing-17-9], so its a trade-off
to consider.
### Object Safety Is Required for Trait Objects
@ -394,7 +418,7 @@ stand in for `Self`, because thats the return type.
The compiler will indicate when youre trying to do something that violates the
rules of object safety in regard to trait objects. For example, lets say we
tried to implement the `Screen` struct in Listing 17-4 to hold types that
tried to implement the `Screen` struct in [Listing 17-4][Listing-17-4] to hold types that
implement the `Clone` trait instead of the `Draw` trait, like this:
```rust,ignore
@ -420,3 +444,13 @@ This error means you cant use this trait as a trait object in this way. If
youre interested in more details on object safety, see [Rust RFC 255].
[Rust RFC 255]: https://github.com/rust-lang/rfcs/blob/master/text/0255-object-safety.md
[Listing-17-3]: ch17-02-trait-objects.html#Listing-17-3
[Listing-17-4]: ch17-02-trait-objects.html#Listing-17-4
[Listing-17-5]: ch17-02-trait-objects.html#Listing-17-5
[Listing-17-6]: ch17-02-trait-objects.html#Listing-17-6
[Listing-17-7]: ch17-02-trait-objects.html#Listing-17-7
[Listing-17-8]: ch17-02-trait-objects.html#Listing-17-8
[Listing-17-9]: ch17-02-trait-objects.html#Listing-17-9
[Listing-17-10]: ch17-02-trait-objects.html#Listing-17-10
[Listing-8-10]: ch08-01-vectors.html#Listing-8-10

View File

@ -28,12 +28,15 @@ Any other changes attempted on a post should have no effect. For example, if we
try to approve a draft blog post before weve requested a review, the post
should remain an unpublished draft.
Listing 17-11 shows this workflow in code form: this is an example usage of the
[Listing 17-11][Listing-17-11] shows this workflow in code form: this is an example usage of the
API well implement in a library crate named `blog`. This wont compile yet
because we havent implemented the `blog` crate yet.
<span class="filename">Filename: src/main.rs</span>
[Listing-17-11]: #Listing-17-11
<a name="Listing-17-11"></a>
```rust,ignore
extern crate blog;
use blog::Post;
@ -82,13 +85,16 @@ make a mistake with the states, like publishing a post before its reviewed.
Lets get started on the implementation of the library! We know we need a
public `Post` struct that holds some content, so well start with the
definition of the struct and an associated public `new` function to create an
instance of `Post`, as shown in Listing 17-12. Well also make a private
instance of `Post`, as shown in [Listing 17-12][Listing-17-12]. Well also make a private
`State` trait. Then `Post` will hold a trait object of `Box<State>` inside an
`Option` in a private field named `state`. Youll see why the `Option` is
necessary in a bit.
<span class="filename">Filename: src/lib.rs</span>
[Listing-17-12]: #Listing-17-12
<a name="Listing-17-12"></a>
```rust
pub struct Post {
state: Option<Box<State>>,
@ -129,16 +135,19 @@ create a `Post` in any other state! In the `Post::new` function, we set the
### Storing the Text of the Post Content
Listing 17-11 showed that we want to be able to call a method named
[Listing 17-11][Listing-17-11] showed that we want to be able to call a method named
`add_text` and pass it a `&str` that is then added to the text content of the
blog post. We implement this as a method rather than exposing the `content`
field as `pub`. This means we can implement a method later that will control
how the `content` fields data is read. The `add_text` method is pretty
straightforward, so lets add the implementation in Listing 17-13 to the `impl
straightforward, so lets add the implementation in [Listing 17-13][Listing-17-13] to the `impl
Post` block:
<span class="filename">Filename: src/lib.rs</span>
[Listing-17-13]: #Listing-17-13
<a name="Listing-17-13"></a>
```rust
# pub struct Post {
# content: String,
@ -167,15 +176,18 @@ support.
Even after weve called `add_text` and added some content to our post, we still
want the `content` method to return an empty string slice because the post is
still in the draft state, as shown on line 8 of Listing 17-11. For now, lets
still in the draft state, as shown on line 8 of [Listing 17-11][Listing-17-11]. For now, lets
implement the `content` method with the simplest thing that will fulfill this
requirement: always returning an empty string slice. Well change this later
once we implement the ability to change a posts state so it can be published.
So far, posts can only be in the draft state, so the post content should always
be empty. Listing 17-14 shows this placeholder implementation:
be empty. [Listing 17-14][Listing-17-14] shows this placeholder implementation:
<span class="filename">Filename: src/lib.rs</span>
[Listing-17-14]: #Listing-17-14
<a name="Listing-17-14"></a>
```rust
# pub struct Post {
# content: String,
@ -192,16 +204,19 @@ impl Post {
<span class="caption">Listing 17-14: Adding a placeholder implementation for
the `content` method on `Post` that always returns an empty string slice</span>
With this added `content` method, everything in Listing 17-11 up to line 8
With this added `content` method, everything in [Listing 17-11][Listing-17-11] up to line 8
works as intended.
### Requesting a Review of the Post Changes Its State
Next, we need to add functionality to request a review of a post, which should
change its state from `Draft` to `PendingReview`. Listing 17-15 shows this code:
change its state from `Draft` to `PendingReview`. [Listing 17-15][Listing-17-15] shows this code:
<span class="filename">Filename: src/lib.rs</span>
[Listing-17-15]: #Listing-17-15
<a name="Listing-17-15"></a>
```rust
# pub struct Post {
# state: Option<Box<State>>,
@ -281,16 +296,19 @@ state is responsible for its own rules.
Well leave the `content` method on `Post` as is, returning an empty string
slice. We can now have a `Post` in the `PendingReview` state as well as in the
`Draft` state, but we want the same behavior in the `PendingReview` state.
Listing 17-11 now works up to line 11!
[Listing 17-11][Listing-17-11] now works up to line 11!
### Adding the `approve` Method that Changes the Behavior of `content`
The `approve` method will be similar to the `request_review` method: it will
set `state` to the value that the current state says it should have when that
state is approved, as shown in Listing 17-16:
state is approved, as shown in [Listing 17-16][Listing-17-16]:
<span class="filename">Filename: src/lib.rs</span>
[Listing-17-16]: #Listing-17-16
<a name="Listing-17-16"></a>
```rust
# pub struct Post {
# state: Option<Box<State>>,
@ -365,10 +383,13 @@ the post should stay in the `Published` state in those cases.
Now we need to update the `content` method on `Post`: if the state is
`Published`, we want to return the value in the posts `content` field;
otherwise, we want to return an empty string slice, as shown in Listing 17-17:
otherwise, we want to return an empty string slice, as shown in [Listing 17-17][Listing-17-17]:
<span class="filename">Filename: src/lib.rs</span>
[Listing-17-17]: #Listing-17-17
<a name="Listing-17-17"></a>
```rust
# trait State {
# fn content<'a>(&self, post: &'a Post) -> &'a str;
@ -413,10 +434,13 @@ take effect on the `&` and the `Box` so the `content` method will ultimately be
called on the type that implements the `State` trait. That means we need to add
`content` to the `State` trait definition, and that is where well put the
logic for what content to return depending on which state we have, as shown in
Listing 17-18:
[Listing 17-18][Listing-17-18]:
<span class="filename">Filename: src/lib.rs</span>
[Listing-17-18]: #Listing-17-18
<a name="Listing-17-18"></a>
```rust
# pub struct Post {
# content: String
@ -452,7 +476,7 @@ Chapter 10. Were taking a reference to a `post` as an argument and returning
reference to part of that `post`, so the lifetime of the returned reference is
related to the lifetime of the `post` argument.
And were done—all of Listing 17-11 now works! Weve implemented the state
And were done—all of [Listing 17-11][Listing-17-11] now works! Weve implemented the state
pattern with the rules of the blog post workflow. The logic related to the
rules lives in the state objects rather than being scattered throughout `Post`.
@ -523,7 +547,7 @@ outside code has no knowledge of them, well encode the states into different
types. Consequently, Rusts type checking system will prevent attempts to use
draft posts where only published posts are allowed by issuing a compiler error.
Lets consider the first part of `main` in Listing 17-11:
Lets consider the first part of `main` in [Listing 17-11][Listing-17-11]:
<span class="filename">Filename: src/main.rs</span>
@ -543,11 +567,14 @@ draft posts dont have the `content` method at all. That way, if we try to get
a draft posts content, well get a compiler error telling us the method
doesnt exist. As a result, it will be impossible for us to accidentally
display draft post content in production, because that code wont even compile.
Listing 17-19 shows the definition of a `Post` struct and a `DraftPost` struct,
[Listing 17-19][Listing-17-19] shows the definition of a `Post` struct and a `DraftPost` struct,
as well as methods on each:
<span class="filename">Filename: src/lib.rs</span>
[Listing-17-19]: #Listing-17-19
<a name="Listing-17-19"></a>
```rust
pub struct Post {
content: String,
@ -604,10 +631,13 @@ pending review state should still not display any content. Lets implement
these constraints by adding another struct, `PendingReviewPost`, defining the
`request_review` method on `DraftPost` to return a `PendingReviewPost`, and
defining an `approve` method on `PendingReviewPost` to return a `Post`, as
shown in Listing 17-20:
shown in [Listing 17-20][Listing-17-20]:
<span class="filename">Filename: src/lib.rs</span>
[Listing-17-20]: #Listing-17-20
<a name="Listing-17-20"></a>
```rust
# pub struct Post {
# content: String,
@ -662,10 +692,13 @@ called on, so we need to add more `let post =` shadowing assignments to save
the returned instances. We also cant have the assertions about the draft and
pending review posts contents be empty strings, nor do we need them: we cant
compile code that tries to use the content of posts in those states any longer.
The updated code in `main` is shown in Listing 17-21:
The updated code in `main` is shown in [Listing 17-21][Listing-17-21]:
<span class="filename">Filename: src/main.rs</span>
[Listing-17-21]: #Listing-17-21
<a name="Listing-17-21"></a>
```rust,ignore
extern crate blog;
use blog::Post;
@ -695,7 +728,7 @@ compile time! This ensures that certain bugs, such as display of the content of
an unpublished post, will be discovered before they make it to production.
Try the tasks suggested for additional requirements that we mentioned at the
start of this section on the `blog` crate as it is after Listing 17-20 to see
start of this section on the `blog` crate as it is after [Listing 17-20][Listing-17-20] to see
what you think about the design of this version of the code. Note that some of
the tasks might be completed already in this design.
@ -723,3 +756,15 @@ option.
Next, well look at patterns, which are another of Rusts features that enable
lots of flexibility. Weve looked at them briefly throughout the book but
havent seen their full capability yet. Lets go!
[Listing-17-11]: ch17-03-oo-design-patterns.html#Listing-17-11
[Listing-17-12]: ch17-03-oo-design-patterns.html#Listing-17-12
[Listing-17-13]: ch17-03-oo-design-patterns.html#Listing-17-13
[Listing-17-14]: ch17-03-oo-design-patterns.html#Listing-17-14
[Listing-17-15]: ch17-03-oo-design-patterns.html#Listing-17-15
[Listing-17-16]: ch17-03-oo-design-patterns.html#Listing-17-16
[Listing-17-17]: ch17-03-oo-design-patterns.html#Listing-17-17
[Listing-17-18]: ch17-03-oo-design-patterns.html#Listing-17-18
[Listing-17-19]: ch17-03-oo-design-patterns.html#Listing-17-19
[Listing-17-20]: ch17-03-oo-design-patterns.html#Listing-17-20
[Listing-17-21]: ch17-03-oo-design-patterns.html#Listing-17-21

View File

@ -38,19 +38,22 @@ way to write the equivalent of a `match` that only matches one case.
Optionally, `if let` can have a corresponding `else` containing code to run if
the pattern in the `if let` doesnt match.
Listing 18-1 shows that its also possible to mix and match `if let`, `else
[Listing 18-1][Listing-18-1] shows that its also possible to mix and match `if let`, `else
if`, and `else if let` expressions. Doing so gives us more flexibility than a
`match` expression in which we can express only one value to compare with the
patterns. Also, the conditions in a series of `if let`, `else if`, `else if
let` arms arent required to relate to each other.
The code in Listing 18-1 shows a series of checks for several conditions that
The code in [Listing 18-1][Listing-18-1] shows a series of checks for several conditions that
decide what the background color should be. For this example, weve created
variables with hardcoded values that a real program might receive from user
input.
<span class="filename">Filename: src/main.rs</span>
[Listing-18-1]: #Listing-18-1
<a name="Listing-18-1"></a>
```rust
fn main() {
let favorite_color: Option<&str> = None;
@ -103,9 +106,12 @@ not alert us to the possible logic bug.
Similar in construction to `if let`, the `while let` conditional loop allows a
`while` loop to run for as long as a pattern continues to match. The example in
Listing 18-2 shows a `while let` loop that uses a vector as a stack and prints
[Listing 18-2][Listing-18-2] shows a `while let` loop that uses a vector as a stack and prints
the values in the vector in the opposite order in which they were pushed.
[Listing-18-2]: #Listing-18-2
<a name="Listing-18-2"></a>
```rust
let mut stack = Vec::new();
@ -134,9 +140,12 @@ construction in Rust code, but we havent yet discussed the pattern that `for`
takes. In a `for` loop, the pattern is the value that directly follows the
keyword `for`, so in `for x in y` the `x` is the pattern.
Listing 18-3 demonstrates how to use a pattern in a `for` loop to destructure,
[Listing 18-3][Listing-18-3] demonstrates how to use a pattern in a `for` loop to destructure,
or break apart, a tuple as part of the `for` loop.
[Listing-18-3]: #Listing-18-3
<a name="Listing-18-3"></a>
```rust
let v = vec!['a', 'b', 'c'];
@ -148,7 +157,7 @@ for (index, value) in v.iter().enumerate() {
<span class="caption">Listing 18-3: Using a pattern in a `for` loop to
destructure a tuple</span>
The code in Listing 18-3 will print the following:
The code in [Listing 18-3][Listing-18-3] will print the following:
```text
a is at index 0
@ -188,8 +197,11 @@ the expression against the pattern and assigns any names it finds. So in the
the variable `x`.” Because the name `x` is the whole pattern, this pattern
effectively means “bind everything to the variable `x`, whatever the value is.”
To see the pattern matching aspect of `let` more clearly, consider Listing
18-4, which uses a pattern with `let` to destructure a tuple.
To see the pattern matching aspect of `let` more clearly, consider [Listing 18-4][Listing-18-4],
which uses a pattern with `let` to destructure a tuple.
[Listing-18-4]: #Listing-18-4
<a name="Listing-18-4"></a>
```rust
let (x, y, z) = (1, 2, 3);
@ -205,9 +217,12 @@ pattern as nesting three individual variable patterns inside it.
If the number of elements in the pattern doesnt match the number of elements
in the tuple, the overall type wont match and well get a compiler error. For
example, Listing 18-5 shows an attempt to destructure a tuple with three
example, [Listing 18-5][Listing-18-5] shows an attempt to destructure a tuple with three
elements into two variables, which wont work.
[Listing-18-5]: #Listing-18-5
<a name="Listing-18-5"></a>
```rust,ignore
let (x, y) = (1, 2, 3);
```
@ -236,10 +251,13 @@ the number of elements in the tuple.
### Function Parameters
Function parameters can also be patterns. The code in Listing 18-6, which
Function parameters can also be patterns. The code in [Listing 18-6][Listing-18-6], which
declares a function named `foo` that takes one parameter named `x` of type
`i32`, should by now look familiar.
[Listing-18-6]: #Listing-18-6
<a name="Listing-18-6"></a>
```rust
fn foo(x: i32) {
// code goes here
@ -250,11 +268,14 @@ fn foo(x: i32) {
parameters</span>
The `x` part is a pattern! As we did with `let`, we could match a tuple in a
functions arguments to the pattern. Listing 18-7 splits the values in a tuple
functions arguments to the pattern. [Listing 18-7][Listing-18-7] splits the values in a tuple
as we pass it to a function.
<span class="filename">Filename: src/main.rs</span>
[Listing-18-7]: #Listing-18-7
<a name="Listing-18-7"></a>
```rust
fn print_coordinates(&(x, y): &(i32, i32)) {
println!("Current location: ({}, {})", x, y);
@ -280,3 +301,11 @@ At this point, youve seen several ways of using patterns, but patterns don
work the same in every place we can use them. In some places, the patterns must
be irrefutable; in other circumstances, they can be refutable. Well discuss
these two concepts next.
[Listing-18-1]: ch18-01-all-the-places-for-patterns.html#Listing-18-1
[Listing-18-2]: ch18-01-all-the-places-for-patterns.html#Listing-18-2
[Listing-18-3]: ch18-01-all-the-places-for-patterns.html#Listing-18-3
[Listing-18-4]: ch18-01-all-the-places-for-patterns.html#Listing-18-4
[Listing-18-5]: ch18-01-all-the-places-for-patterns.html#Listing-18-5
[Listing-18-6]: ch18-01-all-the-places-for-patterns.html#Listing-18-6
[Listing-18-7]: ch18-01-all-the-places-for-patterns.html#Listing-18-7

View File

@ -22,10 +22,13 @@ those cases, youll need to change either the pattern or the construct your
using the pattern with, depending on the intended behavior of the code.
Lets look at an example of what happens when we try to use a refutable pattern
where Rust requires an irrefutable pattern and vice versa. Listing 18-8 shows a
where Rust requires an irrefutable pattern and vice versa. [Listing 18-8][Listing-18-8] shows a
`let` statement, but for the pattern weve specified `Some(x)`, a refutable
pattern. As you might expect, this code will not compile.
[Listing-18-8]: #Listing-18-8
<a name="Listing-18-8"></a>
```rust,ignore
let Some(x) = some_option_value;
```
@ -54,7 +57,10 @@ To fix the problem where we have a refutable pattern where an irrefutable
pattern is needed, we can change the code that uses the pattern: instead of
using `let`, we can use `if let`. Then if the pattern doesnt match, the code
will just skip the code in the curly brackets, giving it a way to continue
validly. Listing 18-9 shows how to fix the code in Listing 18-8.
validly. [Listing 18-9][Listing-18-9] shows how to fix the code in [Listing 18-8][Listing-18-8].
[Listing-18-9]: #Listing-18-9
<a name="Listing-18-9"></a>
```rust
# let some_option_value: Option<i32> = None;
@ -68,9 +74,12 @@ patterns instead of `let`</span>
Weve given the code an out! This code is perfectly valid, although it means we
cannot use an irrefutable pattern without receiving an error. If we give `if
let` a pattern that will always match, such as `x`, as shown in Listing 18-10,
let` a pattern that will always match, such as `x`, as shown in [Listing 18-10][Listing-18-10],
it will not compile.
[Listing-18-10]: #Listing-18-10
<a name="Listing-18-10"></a>
```rust,ignore
if let x = 5 {
println!("{}", x);
@ -100,3 +109,7 @@ this syntax isnt particularly useful and could be replaced with a simpler
Now that you know where to use patterns and the difference between refutable
and irrefutable patterns, lets cover all the syntax we can use to create
patterns.
[Listing-18-8]: ch18-02-refutability.html#Listing-18-8
[Listing-18-9]: ch18-02-refutability.html#Listing-18-9
[Listing-18-10]: ch18-02-refutability.html#Listing-18-10

View File

@ -31,7 +31,7 @@ them many times in the book. However, there is a complication when you use
named variables in `match` expressions. Because `match` starts a new scope,
variables declared as part of a pattern inside the `match` expression will
shadow those with the same name outside the `match` construct, as is the case
with all variables. In Listing 18-11, we declare a variable named `x` with the
with all variables. In [Listing 18-11][Listing-18-11], we declare a variable named `x` with the
value `Some(5)` and a variable `y` with the value `10`. We then create a
`match` expression on the value `x`. Look at the patterns in the match arms and
`println!` at the end, and try to figure out what the code will print before
@ -39,6 +39,9 @@ running this code or reading further.
<span class="filename">Filename: src/main.rs</span>
[Listing-18-11]: #Listing-18-11
<a name="Listing-18-11"></a>
```rust
fn main() {
let x = Some(5);
@ -151,11 +154,14 @@ to use different parts of these values. Lets walk through each value.
#### Destructuring Structs
Listing 18-12 shows a `Point` struct with two fields, `x` and `y`, that we can
[Listing 18-12][Listing-18-12] shows a `Point` struct with two fields, `x` and `y`, that we can
break apart using a pattern with a `let` statement.
<span class="filename">Filename: src/main.rs</span>
[Listing-18-12]: #Listing-18-12
<a name="Listing-18-12"></a>
```rust
struct Point {
x: i32,
@ -184,12 +190,15 @@ Because having variable names match the fields is common and because writing
`let Point { x: x, y: y } = p;` contains a lot of duplication, there is a
shorthand for patterns that match struct fields: you only need to list the name
of the struct field, and the variables created from the pattern will have the
same names. Listing 18-13 shows code that behaves in the same way as the code
in Listing 18-12, but the variables created in the `let` pattern are `x` and
same names. [Listing 18-13][Listing-18-13] shows code that behaves in the same way as the code
in [Listing 18-12][Listing-18-12], but the variables created in the `let` pattern are `x` and
`y` instead of `a` and `b`.
<span class="filename">Filename: src/main.rs</span>
[Listing-18-13]: #Listing-18-13
<a name="Listing-18-13"></a>
```rust
struct Point {
x: i32,
@ -217,12 +226,15 @@ rather than creating variables for all the fields. Doing so allows us to test
some of the fields for particular values while creating variables to
destructure the other fields.
Listing 18-14 shows a `match` expression that separates `Point` values into
[Listing 18-14][Listing-18-14] shows a `match` expression that separates `Point` values into
three cases: points that lie directly on the `x` axis (which is true when `y =
0`), on the `y` axis (`x = 0`), or neither.
<span class="filename">Filename: src/main.rs</span>
[Listing-18-14]: #Listing-18-14
<a name="Listing-18-14"></a>
```rust
# struct Point {
# x: i32,
@ -258,14 +270,17 @@ containing a 0, so this code will print `On the y axis at 7`.
#### Destructuring Enums
Weve destructured enums earlier in this book, for example, when we
destructured `Option<i32>` in Listing 6-5 in Chapter 6. One detail we havent
destructured `Option<i32>` in [Listing 6-5][Listing-6-5] in Chapter 6. One detail we havent
mentioned explicitly is that the pattern to destructure an enum should
correspond to the way the data stored within the enum is defined. As an
example, in Listing 18-15 we use the `Message` enum from Listing 6-2 and write
example, in [Listing 18-15][Listing-18-15] we use the `Message` enum from [Listing 6-2][Listing-6-2] and write
a `match` with patterns that will destructure each inner value.
<span class="filename">Filename: src/main.rs</span>
[Listing-18-15]: #Listing-18-15
<a name="Listing-18-15"></a>
```rust
enum Message {
Quit,
@ -315,7 +330,7 @@ For struct-like enum variants, such as `Message::Move`, we can use a pattern
similar to the pattern we specify to match structs. After the variant name, we
place curly brackets and then list the fields with variables so we break apart
the pieces to use in the code for this arm. Here we use the shorthand form as
we did in Listing 18-13.
we did in [Listing 18-13][Listing-18-13].
For tuple-like enum variants, like `Message::Write` that holds a tuple with one
element and `Message::ChangeColor` that holds a tuple with three elements, the
@ -333,10 +348,13 @@ This technique is especially useful in closures where we have iterators that
iterate over references, but we want to use the values in the closure rather
than the references.
The example in Listing 18-16 iterates over references to `Point` instances in a
The example in [Listing 18-16][Listing-18-16] iterates over references to `Point` instances in a
vector, destructuring the reference and the struct so we can perform
calculations on the `x` and `y` values easily.
[Listing-18-16]: #Listing-18-16
<a name="Listing-18-16"></a>
```rust
# struct Point {
# x: i32,
@ -417,10 +435,13 @@ parts of a value. Lets explore how and why to use each of these patterns.
Weve used the underscore (`_`) as a wildcard pattern that will match any value
but not bind to the value. Although the underscore `_` pattern is especially
useful as the last arm in a `match` expression, we can use it in any pattern,
including function parameters, as shown in Listing 18-17.
including function parameters, as shown in [Listing 18-17][Listing-18-17].
<span class="filename">Filename: src/main.rs</span>
[Listing-18-17]: #Listing-18-17
<a name="Listing-18-17"></a>
```rust
fn foo(_: i32, y: i32) {
println!("This code only uses the y parameter: {}", y);
@ -448,12 +469,15 @@ name instead.
We can also use `_` inside another pattern to ignore just part of a value, for
example, when we want to test for only part of a value but have no use for the
other parts in the corresponding code we want to run. Listing 18-18 shows code
other parts in the corresponding code we want to run. [Listing 18-18][Listing-18-18] shows code
responsible for managing a settings value. The business requirements are that
the user should not be allowed to overwrite an existing customization of a
setting but can unset the setting and can give the setting a value if it is
currently unset.
[Listing-18-18]: #Listing-18-18
<a name="Listing-18-18"></a>
```rust
let mut setting_value = Some(5);
let new_setting_value = Some(10);
@ -486,9 +510,12 @@ In all other cases (if either `setting_value` or `new_setting_value` are
`new_setting_value` to become `setting_value`.
We can also use underscores in multiple places within one pattern to ignore
particular values. Listing 18-19 shows an example of ignoring the second and
particular values. [Listing 18-19][Listing-18-19] shows an example of ignoring the second and
fourth values in a tuple of five items.
[Listing-18-19]: #Listing-18-19
<a name="Listing-18-19"></a>
```rust
let numbers = (2, 4, 8, 16, 32);
@ -510,12 +537,15 @@ If you create a variable but dont use it anywhere, Rust will usually issue a
warning because that could be a bug. But sometimes its useful to create a
variable you wont use yet, such as when youre prototyping or just starting a
project. In this situation, you can tell Rust not to warn you about the unused
variable by starting the name of the variable with an underscore. In Listing
18-20, we create two unused variables, but when we run this code, we should
variable by starting the name of the variable with an underscore. In [Listing 18-20][Listing-18-20],
we create two unused variables, but when we run this code, we should
only get a warning about one of them.
<span class="filename">Filename: src/main.rs</span>
[Listing-18-20]: #Listing-18-20
<a name="Listing-18-20"></a>
```rust
fn main() {
let _x = 5;
@ -532,7 +562,10 @@ warning about not using the variable preceded by the underscore.
Note that there is a subtle difference between using only `_` and using a name
that starts with an underscore. The syntax `_x` still binds the value to the
variable, whereas `_` doesnt bind at all. To show a case where this
distinction matters, Listing 18-21 will provide us with an error.
distinction matters, [Listing 18-21][Listing-18-21] will provide us with an error.
[Listing-18-21]: #Listing-18-21
<a name="Listing-18-21"></a>
```rust,ignore
let s = Some(String::from("Hello!"));
@ -549,9 +582,12 @@ underscore still binds the value, which might take ownership of the value</span>
Well receive an error because the `s` value will still be moved into `_s`,
which prevents us from using `s` again. However, using the underscore by itself
doesnt ever bind to the value. Listing 18-22 will compile without any errors
doesnt ever bind to the value. [Listing 18-22][Listing-18-22] will compile without any errors
because `s` doesnt get moved into `_`.
[Listing-18-22]: #Listing-18-22
<a name="Listing-18-22"></a>
```rust
let s = Some(String::from("Hello!"));
@ -572,11 +608,14 @@ This code works just fine because we never bind `s` to anything; it isnt move
With values that have many parts, we can use the `..` syntax to use only a few
parts and ignore the rest, avoiding the need to list underscores for each
ignored value. The `..` pattern ignores any parts of a value that we havent
explicitly matched in the rest of the pattern. In Listing 18-23, we have a
explicitly matched in the rest of the pattern. In [Listing 18-23][Listing-18-23], we have a
`Point` struct that holds a coordinate in three-dimensional space. In the
`match` expression, we want to operate only on the `x` coordinate and ignore
the values in the `y` and `z` fields.
[Listing-18-23]: #Listing-18-23
<a name="Listing-18-23"></a>
```rust
struct Point {
x: i32,
@ -599,11 +638,14 @@ than having to list `y: _` and `z: _`, particularly when were working with
structs that have lots of fields in situations where only one or two fields are
relevant.
The syntax `..` will expand to as many values as it needs to be. Listing 18-24
The syntax `..` will expand to as many values as it needs to be. [Listing 18-24][Listing-18-24]
shows how to use `..` with a tuple.
<span class="filename">Filename: src/main.rs</span>
[Listing-18-24]: #Listing-18-24
<a name="Listing-18-24"></a>
```rust
fn main() {
let numbers = (2, 4, 8, 16, 32);
@ -624,11 +666,14 @@ In this code, the first and last value are matched with `first` and `last`. The
However, using `..` must be unambiguous. If it is unclear which values are
intended for matching and which should be ignored, Rust will give us an error.
Listing 18-25 shows an example of using `..` ambiguously, so it will not
[Listing 18-25][Listing-18-25] shows an example of using `..` ambiguously, so it will not
compile.
<span class="filename">Filename: src/main.rs</span>
[Listing-18-25]: #Listing-18-25
<a name="Listing-18-25"></a>
```rust,ignore
fn main() {
let numbers = (2, 4, 8, 16, 32);
@ -668,12 +713,15 @@ Lets look at using `ref` to make references so ownership of the values isn
moved to variables in the pattern. Usually, when you match against a pattern,
the variables introduced by the pattern are bound to a value. Rusts ownership
rules mean the value will be moved into the `match` or wherever youre using
the pattern. Listing 18-26 shows an example of a `match` that has a pattern
the pattern. [Listing 18-26][Listing-18-26] shows an example of a `match` that has a pattern
with a variable and then usage of the entire value in the `println!` statement
later, after the `match`. This code will fail to compile because ownership of
part of the `robot_name` value is transferred to the `name` variable in the
pattern of the first `match` arm.
[Listing-18-26]: #Listing-18-26
<a name="Listing-18-26"></a>
```rust,ignore
let robot_name = Some(String::from("Bors"));
@ -703,7 +751,10 @@ reference in the value. Because `&` already has that meaning in patterns, we
cant use `&` to create a reference in a pattern.
Instead, to create a reference in a pattern, we use the `ref` keyword before
the new variable, as shown in Listing 18-27.
the new variable, as shown in [Listing 18-27][Listing-18-27].
[Listing-18-27]: #Listing-18-27
<a name="Listing-18-27"></a>
```rust
let robot_name = Some(String::from("Bors"));
@ -726,9 +777,12 @@ to the data in `robot_name` rather than moving it.
To create a mutable reference so were able to mutate a value matched in a
pattern, we use `ref mut` instead of `&mut`. The reason is, again, that in
patterns, the latter is for matching existing mutable references, not creating
new ones. Listing 18-28 shows an example of a pattern creating a mutable
new ones. [Listing 18-28][Listing-18-28] shows an example of a pattern creating a mutable
reference.
[Listing-18-28]: #Listing-18-28
<a name="Listing-18-28"></a>
```rust
let mut robot_name = Some(String::from("Bors"));
@ -754,10 +808,13 @@ a `match` arm that must also match, along with the pattern matching, for that
arm to be chosen. Match guards are useful for expressing more complex ideas
than a pattern alone allows.
The condition can use variables created in the pattern. Listing 18-29 shows a
The condition can use variables created in the pattern. [Listing 18-29][Listing-18-29] shows a
`match` where the first arm has the pattern `Some(x)` and also has a match
guard of `if x < 5`.
[Listing-18-29]: #Listing-18-29
<a name="Listing-18-29"></a>
```rust
let num = Some(4);
@ -783,15 +840,18 @@ therefore matches any `Some` variant.
There is no way to express the `if x < 5` condition within a pattern, so the
match guard gives us the ability to express this logic.
In Listing 18-11, we mentioned that we could use match guards to solve our
In [Listing 18-11][Listing-18-11], we mentioned that we could use match guards to solve our
pattern-shadowing problem. Recall that a new variable was created inside the
pattern in the `match` expression instead of using the variable outside the
`match`. That new variable meant we couldnt test against the value of the
outer variable. Listing 18-30 shows how we can use a match guard to fix this
outer variable. [Listing 18-30][Listing-18-30] shows how we can use a match guard to fix this
problem.
<span class="filename">Filename: src/main.rs</span>
[Listing-18-30]: #Listing-18-30
<a name="Listing-18-30"></a>
```rust
fn main() {
let x = Some(5);
@ -823,12 +883,15 @@ we can look for a value that has the same value as the outer `y` by comparing
`n` to `y`.
You can also use the *or* operator `|` in a match guard to specify multiple
patterns; the match guard condition will apply to all the patterns. Listing
18-31 shows the precedence of combining a match guard with a pattern that uses
patterns; the match guard condition will apply to all the patterns. [Listing 18-31][Listing-18-31]
shows the precedence of combining a match guard with a pattern that uses
`|`. The important part of this example is that the `if y` match guard applies
to `4`, `5`, *and* `6`, even though it might look like `if y` only applies to
`6`.
[Listing-18-31]: #Listing-18-31
<a name="Listing-18-31"></a>
```rust
let x = 4;
let y = false;
@ -869,13 +932,16 @@ were applied only to the final value in the list of values specified using the
### `@` Bindings
The *at* operator (`@`) lets us create a variable that holds a value at the
same time were testing that value to see whether it matches a pattern. Listing
18-32 shows an example where we want to test that a `Message::Hello` `id` field
same time were testing that value to see whether it matches a pattern. [Listing 18-32][Listing-18-32]
shows an example where we want to test that a `Message::Hello` `id` field
is within the range `3...7`. But we also want to bind the value to the variable
`id_variable` so we can use it in the code associated with the arm. We could
name this variable `id`, the same as the field, but for this example well use
a different name.
[Listing-18-32]: #Listing-18-32
<a name="Listing-18-32"></a>
```rust
enum Message {
Hello { id: i32 },
@ -929,3 +995,28 @@ variables. We can create simple or complex patterns to suit our needs.
Next, for the penultimate chapter of the book, well look at some advanced
aspects of a variety of Rusts features.
[Listing-18-11]: ch18-03-pattern-syntax.html#Listing-18-11
[Listing-18-12]: ch18-03-pattern-syntax.html#Listing-18-12
[Listing-18-13]: ch18-03-pattern-syntax.html#Listing-18-13
[Listing-18-14]: ch18-03-pattern-syntax.html#Listing-18-14
[Listing-18-15]: ch18-03-pattern-syntax.html#Listing-18-15
[Listing-18-16]: ch18-03-pattern-syntax.html#Listing-18-16
[Listing-18-17]: ch18-03-pattern-syntax.html#Listing-18-17
[Listing-18-18]: ch18-03-pattern-syntax.html#Listing-18-18
[Listing-18-19]: ch18-03-pattern-syntax.html#Listing-18-19
[Listing-18-20]: ch18-03-pattern-syntax.html#Listing-18-20
[Listing-18-21]: ch18-03-pattern-syntax.html#Listing-18-21
[Listing-18-22]: ch18-03-pattern-syntax.html#Listing-18-22
[Listing-18-23]: ch18-03-pattern-syntax.html#Listing-18-23
[Listing-18-24]: ch18-03-pattern-syntax.html#Listing-18-24
[Listing-18-25]: ch18-03-pattern-syntax.html#Listing-18-25
[Listing-18-26]: ch18-03-pattern-syntax.html#Listing-18-26
[Listing-18-27]: ch18-03-pattern-syntax.html#Listing-18-27
[Listing-18-28]: ch18-03-pattern-syntax.html#Listing-18-28
[Listing-18-29]: ch18-03-pattern-syntax.html#Listing-18-29
[Listing-18-30]: ch18-03-pattern-syntax.html#Listing-18-30
[Listing-18-31]: ch18-03-pattern-syntax.html#Listing-18-31
[Listing-18-32]: ch18-03-pattern-syntax.html#Listing-18-32
[Listing-6-5]: ch06-02-match.html#Listing-6-5
[Listing-6-2]: ch06-01-defining-an-enum.html#Listing-6-2

View File

@ -85,9 +85,12 @@ By opting out of having Rust enforce these guarantees, you can give up
guaranteed safety in exchange for greater performance or the ability to
interface with another language or hardware where Rusts guarantees dont apply.
Listing 19-1 shows how to create an immutable and a mutable raw pointer from
[Listing 19-1][Listing-19-1] shows how to create an immutable and a mutable raw pointer from
references.
[Listing-19-1]: #Listing-19-1
<a name="Listing-19-1"></a>
```rust
let mut num = 5;
@ -108,12 +111,15 @@ pointers are valid, but we cant make that assumption about just any raw
pointer.
Next, well create a raw pointer whose validity we cant be so certain of.
Listing 19-2 shows how to create a raw pointer to an arbitrary location in
[Listing 19-2][Listing-19-2] shows how to create a raw pointer to an arbitrary location in
memory. Trying to use arbitrary memory is undefined: there might be data at
that address or there might not, the compiler might optimize the code so there
is no memory access, or the program might error with a segmentation fault.
Usually, there is no good reason to write code like this, but it is possible.
[Listing-19-2]: #Listing-19-2
<a name="Listing-19-2"></a>
```rust
let address = 0x012345usize;
let r = address as *const i32;
@ -123,9 +129,12 @@ let r = address as *const i32;
memory address</span>
Recall that we can create raw pointers in safe code, but we cant *dereference*
raw pointers and read the data being pointed to. In Listing 19-3, we use the
raw pointers and read the data being pointed to. In [Listing 19-3][Listing-19-3], we use the
dereference operator `*` on a raw pointer that requires an `unsafe` block.
[Listing-19-3]: #Listing-19-3
<a name="Listing-19-3"></a>
```rust
let mut num = 5;
@ -144,7 +153,7 @@ unsafe {
Creating a pointer does no harm; its only when we try to access the value that
it points at that we might end up dealing with an invalid value.
Note also that in Listing 19-1 and 19-3, we created `*const i32` and `*mut i32`
Note also that in [Listing 19-1][Listing-19-1] and 19-3, we created `*const i32` and `*mut i32`
raw pointers that both pointed to the same memory location, where `num` is
stored. If we instead tried to create an immutable and a mutable reference to
`num`, the code would not have compiled because Rusts ownership rules dont
@ -210,7 +219,10 @@ a common abstraction. As an example, lets study a function from the standard
library, `split_at_mut`, that requires some unsafe code and explore how we
might implement it. This safe method is defined on mutable slices: it takes one
slice and makes it two by splitting the slice at the index given as an
argument. Listing 19-4 shows how to use `split_at_mut`.
argument. [Listing 19-4][Listing-19-4] shows how to use `split_at_mut`.
[Listing-19-4]: #Listing-19-4
<a name="Listing-19-4"></a>
```rust
let mut v = vec![1, 2, 3, 4, 5, 6];
@ -227,10 +239,13 @@ assert_eq!(b, &mut [4, 5, 6]);
function</span>
We cant implement this function using only safe Rust. An attempt might look
something like Listing 19-5, which wont compile. For simplicity, well
something like [Listing 19-5][Listing-19-5], which wont compile. For simplicity, well
implement `split_at_mut` as a function rather than a method and only for slices
of `i32` values rather than for a generic type `T`.
[Listing-19-5]: #Listing-19-5
<a name="Listing-19-5"></a>
```rust,ignore
fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
let len = slice.len();
@ -255,7 +270,7 @@ Then we return two mutable slices in a tuple: one from the start of the
original slice to the `mid` index and another from `mid` to the end of the
slice.
When we try to compile the code in Listing 19-5, well get an error.
When we try to compile the code in [Listing 19-5][Listing-19-5], well get an error.
```text
error[E0499]: cannot borrow `*slice` as mutable more than once at a time
@ -275,9 +290,12 @@ Borrowing different parts of a slice is fundamentally okay because the two
slices arent overlapping, but Rust isnt smart enough to know this. When we
know code is okay, but Rust doesnt, its time to reach for unsafe code.
Listing 19-6 shows how to use an `unsafe` block, a raw pointer, and some calls
[Listing 19-6][Listing-19-6] shows how to use an `unsafe` block, a raw pointer, and some calls
to unsafe functions to make the implementation of `split_at_mut` work.
[Listing-19-6]: #Listing-19-6
<a name="Listing-19-6"></a>
```rust
use std::slice;
@ -328,10 +346,13 @@ abstraction to the unsafe code with an implementation of the function that uses
`unsafe` code in a safe way, because it creates only valid pointers from the
data this function has access to.
In contrast, the use of `slice::from_raw_parts_mut` in Listing 19-7 would
In contrast, the use of `slice::from_raw_parts_mut` in [Listing 19-7][Listing-19-7] would
likely crash when the slice is used. This code takes an arbitrary memory
location and creates a slice 10,000 items long.
[Listing-19-7]: #Listing-19-7
<a name="Listing-19-7"></a>
```rust
use std::slice;
@ -358,7 +379,7 @@ and use of a *Foreign Function Interface (FFI)*. An FFI is a way for a
programming language to define functions and enable a different (foreign)
programming language to call those functions.
Listing 19-8 demonstrates how to set up an integration with the `abs` function
[Listing 19-8][Listing-19-8] demonstrates how to set up an integration with the `abs` function
from the C standard library. Functions declared within `extern` blocks are
always unsafe to call from Rust code. The reason is that other languages dont
enforce Rusts rules and guarantees, and Rust cant check them, so
@ -366,6 +387,9 @@ responsibility falls on the programmer to ensure safety.
<span class="filename">Filename: src/main.rs</span>
[Listing-19-8]: #Listing-19-8
<a name="Listing-19-8"></a>
```rust
extern "C" {
fn abs(input: i32) -> i32;
@ -418,12 +442,15 @@ Until now, weve not talked about *global variables*, which Rust does support
but can be problematic with Rusts ownership rules. If two threads are
accessing the same mutable global variable, it can cause a data race.
In Rust, global variables are called *static* variables. Listing 19-9 shows an
In Rust, global variables are called *static* variables. [Listing 19-9][Listing-19-9] shows an
example declaration and use of a static variable with a string slice as a
value.
<span class="filename">Filename: src/main.rs</span>
[Listing-19-9]: #Listing-19-9
<a name="Listing-19-9"></a>
```rust
static HELLO_WORLD: &str = "Hello, world!";
@ -450,11 +477,14 @@ are allowed to duplicate their data whenever theyre used.
Another difference between constants and static variables is that static
variables can be mutable. Accessing and modifying mutable static variables is
*unsafe*. Listing 19-10 shows how to declare, access, and modify a mutable
*unsafe*. [Listing 19-10][Listing-19-10] shows how to declare, access, and modify a mutable
static variable named `COUNTER`.
<span class="filename">Filename: src/main.rs</span>
[Listing-19-10]: #Listing-19-10
<a name="Listing-19-10"></a>
```rust
static mut COUNTER: u32 = 0;
@ -494,7 +524,10 @@ The final action that works only with `unsafe` is implementing an unsafe trait.
A trait is unsafe when at least one of its methods has some invariant that the
compiler cant verify. We can declare that a trait is `unsafe` by adding the
`unsafe` keyword before `trait` and marking the implementation of the trait as
`unsafe` too, as shown in Listing 19-11.
`unsafe` too, as shown in [Listing 19-11][Listing-19-11].
[Listing-19-11]: #Listing-19-11
<a name="Listing-19-11"></a>
```rust
unsafe trait Foo {
@ -529,3 +562,15 @@ isnt wrong or even frowned upon. But it is trickier to get `unsafe` code
correct because the compiler cant help uphold memory safety. When you have a
reason to use `unsafe` code, you can do so, and having the explicit `unsafe`
annotation makes it easier to track down the source of problems if they occur.
[Listing-19-1]: ch19-01-unsafe-rust.html#Listing-19-1
[Listing-19-2]: ch19-01-unsafe-rust.html#Listing-19-2
[Listing-19-3]: ch19-01-unsafe-rust.html#Listing-19-3
[Listing-19-4]: ch19-01-unsafe-rust.html#Listing-19-4
[Listing-19-5]: ch19-01-unsafe-rust.html#Listing-19-5
[Listing-19-6]: ch19-01-unsafe-rust.html#Listing-19-6
[Listing-19-7]: ch19-01-unsafe-rust.html#Listing-19-7
[Listing-19-8]: ch19-01-unsafe-rust.html#Listing-19-8
[Listing-19-9]: ch19-01-unsafe-rust.html#Listing-19-9
[Listing-19-10]: ch19-01-unsafe-rust.html#Listing-19-10
[Listing-19-11]: ch19-01-unsafe-rust.html#Listing-19-11

View File

@ -18,11 +18,14 @@ lifetime. To explore lifetime subtyping, imagine we want to write a parser.
Well use a structure called `Context` that holds a reference to the string
were parsing. Well write a parser that will parse this string and return
success or failure. The parser will need to borrow the `Context` to do the
parsing. Listing 19-12 implements this parser code, except the code doesnt
parsing. [Listing 19-12][Listing-19-12] implements this parser code, except the code doesnt
have the required lifetime annotations, so it wont compile.
<span class="filename">Filename: src/lib.rs</span>
[Listing-19-12]: #Listing-19-12
<a name="Listing-19-12"></a>
```rust,ignore
struct Context(&str);
@ -62,7 +65,7 @@ lifetimes involved.
To get this code to compile, we need to fill in the lifetime parameters for the
string slice in `Context` and the reference to the `Context` in `Parser`. The
most straightforward way to do this is to use the same lifetime name
everywhere, as shown in Listing 19-13. Recall from the “Lifetime Annotations in
everywhere, as shown in [Listing 19-13][Listing-19-13]. Recall from the “Lifetime Annotations in
Struct Definitions” section in Chapter 10 that each of `struct Context<'a>`,
`struct Parser<'a>`, and `impl<'a>` is declaring a new lifetime parameter.
While their names happen to all be the same, the three lifetime parameters
@ -70,6 +73,9 @@ declared in this example arent related.
<span class="filename">Filename: src/lib.rs</span>
[Listing-19-13]: #Listing-19-13
<a name="Listing-19-13"></a>
```rust
struct Context<'a>(&'a str);
@ -93,12 +99,15 @@ also lives as long as the reference to the `Context` in `Parser`. Rusts
compiler error message stated that lifetime parameters were required for these
references, and weve now added lifetime parameters.
Next, in Listing 19-14, well add a function that takes an instance of
Next, in [Listing 19-14][Listing-19-14], well add a function that takes an instance of
`Context`, uses a `Parser` to parse that context, and returns what `parse`
returns. This code doesnt quite work.
<span class="filename">Filename: src/lib.rs</span>
[Listing-19-14]: #Listing-19-14
<a name="Listing-19-14"></a>
```rust,ignore
fn parse_context(context: Context) -> Result<(), &str> {
Parser { context: &context }.parse()
@ -155,8 +164,8 @@ references in this code to always be valid. The `Parser` were creating and th
`context` parameter go out of scope at the end of the function, because
`parse_context` takes ownership of `context`.
To figure out why these errors occur, lets look at the definitions in Listing
19-13 again, specifically the references in the signature of the `parse` method:
To figure out why these errors occur, lets look at the definitions in [Listing 19-13][Listing-19-13]
again, specifically the references in the signature of the `parse` method:
```rust,ignore
fn parse(&self) -> Result<(), &str> {
@ -205,7 +214,7 @@ different lifetimes and that the return value of `parse_context` is tied to the
lifetime of the string slice in `Context`.
First, well try giving `Parser` and `Context` different lifetime parameters,
as shown in Listing 19-15. Well use `'s` and `'c` as lifetime parameter names
as shown in [Listing 19-15][Listing-19-15]. Well use `'s` and `'c` as lifetime parameter names
to clarify which lifetime goes with the string slice in `Context` and which
goes with the reference to `Context` in `Parser`. Note that this solution wont
completely fix the problem, but its a start. Well look at why this fix isnt
@ -213,6 +222,9 @@ sufficient when we try to compile.
<span class="filename">Filename: src/lib.rs</span>
[Listing-19-15]: #Listing-19-15
<a name="Listing-19-15"></a>
```rust,ignore
struct Context<'s>(&'s str);
@ -235,7 +247,7 @@ fn parse_context(context: Context) -> Result<(), &str> {
for the references to the string slice and to `Context`</span>
Weve annotated the lifetimes of the references in all the same places that we
annotated them in Listing 19-13. But this time we used different parameters
annotated them in [Listing 19-13][Listing-19-13]. But this time we used different parameters
depending on whether the reference goes with the string slice or with
`Context`. Weve also added an annotation to the string slice part of the
return value of `parse` to indicate that it goes with the lifetime of the
@ -312,10 +324,13 @@ As an example, consider a type that is a wrapper over references. Recall the
section in Chapter 15: its `borrow` and `borrow_mut` methods return the types
`Ref` and `RefMut`, respectively. These types are wrappers over references that
keep track of the borrowing rules at runtime. The definition of the `Ref`
struct is shown in Listing 19-16, without lifetime bounds for now.
struct is shown in [Listing 19-16][Listing-19-16], without lifetime bounds for now.
<span class="filename">Filename: src/lib.rs</span>
[Listing-19-16]: #Listing-19-16
<a name="Listing-19-16"></a>
```rust,ignore
struct Ref<'a, T>(&'a T);
```
@ -354,9 +369,12 @@ consider adding an explicit lifetime bound `T: 'a` so that the reference type
`&'a T` does not outlive the data it points at
```
Listing 19-17 shows how to apply this advice by specifying the lifetime bound
[Listing 19-17][Listing-19-17] shows how to apply this advice by specifying the lifetime bound
when we declare the generic type `T`.
[Listing-19-17]: #Listing-19-17
<a name="Listing-19-17"></a>
```rust
struct Ref<'a, T: 'a>(&'a T);
```
@ -369,10 +387,13 @@ type, but if it contains any references, the references must live at least as
long as `'a`.
We could solve this problem in a different way, as shown in the definition of a
`StaticRef` struct in Listing 19-18, by adding the `'static` lifetime bound on
`StaticRef` struct in [Listing 19-18][Listing-19-18], by adding the `'static` lifetime bound on
`T`. This means if `T` contains any references, they must have the `'static`
lifetime.
[Listing-19-18]: #Listing-19-18
<a name="Listing-19-18"></a>
```rust
struct StaticRef<T: 'static>(&'static T);
```
@ -395,13 +416,16 @@ In Chapter 17 in the “Using Trait Objects that Allow for Values of Different
Types” section, we discussed trait objects, consisting of a trait behind a
reference, that allow us to use dynamic dispatch. We havent yet discussed what
happens if the type implementing the trait in the trait object has a lifetime
of its own. Consider Listing 19-19 where we have a trait `Red` and a struct
of its own. Consider [Listing 19-19][Listing-19-19] where we have a trait `Red` and a struct
`Ball`. The `Ball` struct holds a reference (and thus has a lifetime parameter)
and also implements trait `Red`. We want to use an instance of `Ball` as the
trait object `Box<Red>`.
<span class="filename">Filename: src/main.rs</span>
[Listing-19-19]: #Listing-19-19
<a name="Listing-19-19"></a>
```rust
trait Red { }
@ -441,3 +465,12 @@ bounds, the syntax adding a lifetime bound means that any implementor of the
specified in the trait object bounds as those references.
Next, lets look at some other advanced features that manage traits.
[Listing-19-12]: ch19-02-advanced-lifetimes.html#Listing-19-12
[Listing-19-13]: ch19-02-advanced-lifetimes.html#Listing-19-13
[Listing-19-14]: ch19-02-advanced-lifetimes.html#Listing-19-14
[Listing-19-15]: ch19-02-advanced-lifetimes.html#Listing-19-15
[Listing-19-16]: ch19-02-advanced-lifetimes.html#Listing-19-16
[Listing-19-17]: ch19-02-advanced-lifetimes.html#Listing-19-17
[Listing-19-18]: ch19-02-advanced-lifetimes.html#Listing-19-18
[Listing-19-19]: ch19-02-advanced-lifetimes.html#Listing-19-19

View File

@ -23,7 +23,10 @@ standard library provides. The associated type is named `Item` and stands in
for the type of the values the type implementing the `Iterator` trait is
iterating over. In “The `Iterator` Trait and the `next` Method” section of
Chapter 13, we mentioned that the definition of the `Iterator` trait is as
shown in Listing 19-20.
shown in [Listing 19-20][Listing-19-20].
[Listing-19-20]: #Listing-19-20
<a name="Listing-19-20"></a>
```rust
pub trait Iterator {
@ -47,7 +50,7 @@ handle. So why use associated types?
Lets examine the difference between the two concepts with an example from
Chapter 13 that implements the `Iterator` trait on the `Counter` struct. In
Listing 13-21, we specified that the `Item` type was `u32`:
[Listing 13-21][Listing-13-21], we specified that the `Item` type was `u32`:
<span class="filename">Filename: src/lib.rs</span>
@ -60,7 +63,10 @@ impl Iterator for Counter {
```
This syntax seems comparable to that of generics. So why not just define the
`Iterator` trait with generics, as shown in Listing 19-21?
`Iterator` trait with generics, as shown in [Listing 19-21][Listing-19-21]?
[Listing-19-21]: #Listing-19-21
<a name="Listing-19-21"></a>
```rust
pub trait Iterator<T> {
@ -71,7 +77,7 @@ pub trait Iterator<T> {
<span class="caption">Listing 19-21: A hypothetical definition of the
`Iterator` trait using generics</span>
The difference is that when using generics, as in Listing 19-21, we must
The difference is that when using generics, as in [Listing 19-21][Listing-19-21], we must
annotate the types in each implementation; because we can also implement
`Iterator<String> for Counter` or any other type, we could have multiple
implementations of `Iterator` for `Counter`. In other words, when a trait has a
@ -81,7 +87,7 @@ the concrete types of the generic type parameters each time. When we use the
indicate which implementation of `Iterator` we want to use.
With associated types, we dont need to annotate types because we cant
implement a trait on a type multiple times. In Listing 19-20 with the
implement a trait on a type multiple times. In [Listing 19-20][Listing-19-20] with the
definition that uses associated types, we can only choose what the type of
`Item` will be once, because there can only be one `impl Iterator for Counter`.
We dont have to specify that we want an iterator of `u32` values everywhere
@ -102,12 +108,15 @@ overloading. *Operator overloading* is customizing the behavior of an operator
Rust doesnt allow you to create your own operators or overload arbitrary
operators. But you can overload the operations and corresponding traits listed
in `std::ops` by implementing the traits associated with the operator. For
example, in Listing 19-22 we overload the `+` operator to add two `Point`
example, in [Listing 19-22][Listing-19-22] we overload the `+` operator to add two `Point`
instances together. We do this by implementing the `Add` trait on a `Point`
struct:
<span class="filename">Filename: src/main.rs</span>
[Listing-19-22]: #Listing-19-22
<a name="Listing-19-22"></a>
```rust
use std::ops::Add;
@ -169,10 +178,13 @@ default.
We have two structs, `Millimeters` and `Meters`, holding values in different
units. We want to add values in millimeters to values in meters and have the
implementation of `Add` do the conversion correctly. We can implement `Add` for
`Millimeters` with `Meters` as the `RHS`, as shown in Listing 19-23.
`Millimeters` with `Meters` as the `RHS`, as shown in [Listing 19-23][Listing-19-23].
<span class="filename">Filename: src/lib.rs</span>
[Listing-19-23]: #Listing-19-23
<a name="Listing-19-23"></a>
```rust
use std::ops::Add;
@ -219,13 +231,16 @@ on one type. Its also possible to implement a method directly on the type wit
the same name as methods from traits.
When calling methods with the same name, youll need to tell Rust which one you
want to use. Consider the code in Listing 19-24 where weve defined two traits,
want to use. Consider the code in [Listing 19-24][Listing-19-24] where weve defined two traits,
`Pilot` and `Wizard`, that both have a method called `fly`. We then implement
both traits on a type `Human` that already has a method named `fly` implemented
on it. Each `fly` method does something different.
<span class="filename">Filename: src/main.rs</span>
[Listing-19-24]: #Listing-19-24
<a name="Listing-19-24"></a>
```rust
trait Pilot {
fn fly(&self);
@ -261,10 +276,13 @@ method and are implemented on the `Human` type, and a `fly` method is
implemented on `Human` directly</span>
When we call `fly` on an instance of `Human`, the compiler defaults to calling
the method that is directly implemented on the type, as shown in Listing 19-25.
the method that is directly implemented on the type, as shown in [Listing 19-25][Listing-19-25].
<span class="filename">Filename: src/main.rs</span>
[Listing-19-25]: #Listing-19-25
<a name="Listing-19-25"></a>
```rust
# trait Pilot {
# fn fly(&self);
@ -308,10 +326,13 @@ called the `fly` method implemented on `Human` directly.
To call the `fly` methods from either the `Pilot` trait or the `Wizard` trait,
we need to use more explicit syntax to specify which `fly` method we mean.
Listing 19-26 demonstrates this syntax.
[Listing 19-26][Listing-19-26] demonstrates this syntax.
<span class="filename">Filename: src/main.rs</span>
[Listing-19-26]: #Listing-19-26
<a name="Listing-19-26"></a>
```rust
# trait Pilot {
# fn fly(&self);
@ -355,7 +376,7 @@ want to call</span>
Specifying the trait name before the method name clarifies to Rust which
implementation of `fly` we want to call. We could also write
`Human::fly(&person)`, which is equivalent to the `person.fly()` that we used
in Listing 19-26, but this is a bit longer to write if we dont need to
in [Listing 19-26][Listing-19-26], but this is a bit longer to write if we dont need to
disambiguate.
Running this code prints the following:
@ -373,12 +394,15 @@ trait to use based on the type of `self`.
However, associated functions that are part of traits dont have a `self`
parameter. When two types in the same scope implement that trait, Rust cant
figure out which type you mean unless you use *fully qualified syntax*. For
example, the `Animal` trait in Listing 19-27 has the associated function
example, the `Animal` trait in [Listing 19-27][Listing-19-27] has the associated function
`baby_name`, the implementation of `Animal` for the struct `Dog`, and the
associated function `baby_name` defined on `Dog` directly.
<span class="filename">Filename: src/main.rs</span>
[Listing-19-27]: #Listing-19-27
<a name="Listing-19-27"></a>
```rust
trait Animal {
fn baby_name() -> String;
@ -424,11 +448,14 @@ A baby dog is called a Spot
This output isnt what we wanted. We want to call the `baby_name` function that
is part of the `Animal` trait that we implemented on `Dog` so the code prints
`A baby dog is called a puppy`. The technique of specifying the trait name that
we used in Listing 19-26 doesnt help here; if we change `main` to the code in
Listing 19-28, well get a compilation error.
we used in [Listing 19-26][Listing-19-26] doesnt help here; if we change `main` to the code in
[Listing 19-28][Listing-19-28], well get a compilation error.
<span class="filename">Filename: src/main.rs</span>
[Listing-19-28]: #Listing-19-28
<a name="Listing-19-28"></a>
```rust,ignore
fn main() {
println!("A baby dog is called a {}", Animal::baby_name());
@ -454,11 +481,14 @@ error[E0283]: type annotations required: cannot resolve `_: Animal`
```
To disambiguate and tell Rust that we want to use the implementation of
`Animal` for `Dog`, we need to use fully qualified syntax. Listing 19-29
`Animal` for `Dog`, we need to use fully qualified syntax. [Listing 19-29][Listing-19-29]
demonstrates how to use fully qualified syntax.
<span class="filename">Filename: src/main.rs</span>
[Listing-19-29]: #Listing-19-29
<a name="Listing-19-29"></a>
```rust
# trait Animal {
# fn baby_name() -> String;
@ -535,10 +565,13 @@ functionality. Therefore, we need to specify that the `OutlinePrint` trait will
work only for types that also implement `Display` and provide the functionality
that `OutlinePrint` needs. We can do that in the trait definition by specifying
`OutlinePrint: Display`. This technique is similar to adding a trait bound to
the trait. Listing 19-30 shows an implementation of the `OutlinePrint` trait.
the trait. [Listing 19-30][Listing-19-30] shows an implementation of the `OutlinePrint` trait.
<span class="filename">Filename: src/main.rs</span>
[Listing-19-30]: #Listing-19-30
<a name="Listing-19-30"></a>
```rust
use std::fmt;
@ -635,10 +668,13 @@ As an example, lets say we want to implement `Display` on `Vec<T>`, which the
orphan rule prevents us from doing directly because the `Display` trait and the
`Vec<T>` type are defined outside our crate. We can make a `Wrapper` struct
that holds an instance of `Vec<T>`; then we can implement `Display` on
`Wrapper` and use the `Vec<T>` value, as shown in Listing 19-31.
`Wrapper` and use the `Vec<T>` value, as shown in [Listing 19-31][Listing-19-31].
<span class="filename">Filename: src/main.rs</span>
[Listing-19-31]: #Listing-19-31
<a name="Listing-19-31"></a>
```rust
use std::fmt;
@ -678,3 +714,17 @@ methods we do want manually.
Now you know how the newtype pattern is used in relation to traits; its also a
useful pattern even when traits are not involved. Lets switch focus and look
at some advanced ways to interact with Rusts type system.
[Listing-19-20]: ch19-03-advanced-traits.html#Listing-19-20
[Listing-19-21]: ch19-03-advanced-traits.html#Listing-19-21
[Listing-19-22]: ch19-03-advanced-traits.html#Listing-19-22
[Listing-19-23]: ch19-03-advanced-traits.html#Listing-19-23
[Listing-19-24]: ch19-03-advanced-traits.html#Listing-19-24
[Listing-19-25]: ch19-03-advanced-traits.html#Listing-19-25
[Listing-19-26]: ch19-03-advanced-traits.html#Listing-19-26
[Listing-19-27]: ch19-03-advanced-traits.html#Listing-19-27
[Listing-19-28]: ch19-03-advanced-traits.html#Listing-19-28
[Listing-19-29]: ch19-03-advanced-traits.html#Listing-19-29
[Listing-19-30]: ch19-03-advanced-traits.html#Listing-19-30
[Listing-19-31]: ch19-03-advanced-traits.html#Listing-19-31
[Listing-13-21]: ch13-02-iterators.html#Listing-13-21

View File

@ -14,7 +14,7 @@ discuss the `!` type and dynamically sized types.
The newtype pattern is useful for tasks beyond those weve discussed so far,
including statically enforcing that values are never confused and indicating
the units of a value. You saw an example of using newtypes to indicate units in
Listing 19-23: recall that the `Millimeters` and `Meters` structs wrapped `u32`
[Listing 19-23][Listing-19-23]: recall that the `Millimeters` and `Meters` structs wrapped `u32`
values in a newtype. If we wrote a function with a parameter of type
`Millimeters`, we couldnt compile a program that accidentally tried to call
that function with a value of type `Meters` or a plain `u32`.
@ -44,7 +44,7 @@ type Kilometers = i32;
```
Now, the alias `Kilometers` is a *synonym* for `i32`; unlike the `Millimeters`
and `Meters` types we created in Listing 19-23, `Kilometers` is not a separate,
and `Meters` types we created in [Listing 19-23][Listing-19-23], `Kilometers` is not a separate,
new type. Values that have the type `Kilometers` will be treated the same as
values of type `i32`:
@ -71,7 +71,10 @@ Box<Fn() + Send + 'static>
Writing this lengthy type in function signatures and as type annotations all
over the code can be tiresome and error prone. Imagine having a project full of
code like that in Listing 19-32.
code like that in [Listing 19-32][Listing-19-32].
[Listing-19-32]: #Listing-19-32
<a name="Listing-19-32"></a>
```rust
let f: Box<Fn() + Send + 'static> = Box::new(|| println!("hi"));
@ -89,9 +92,12 @@ fn returns_long_type() -> Box<Fn() + Send + 'static> {
<span class="caption">Listing 19-32: Using a long type in many places</span>
A type alias makes this code more manageable by reducing the repetition. In
Listing 19-33, weve introduced an alias named `Thunk` for the verbose type and
[Listing 19-33][Listing-19-33], weve introduced an alias named `Thunk` for the verbose type and
can replace all uses of the type with the shorter alias `Thunk`.
[Listing-19-33]: #Listing-19-33
<a name="Listing-19-33"></a>
```rust
type Thunk = Box<Fn() + Send + 'static>;
@ -181,7 +187,10 @@ never are called *diverging functions*. We cant create values of the type `!`
so `bar` can never possibly return.
But what use is a type you can never create values for? Recall the code from
Listing 2-5; weve reproduced part of it here in Listing 19-34.
[Listing 2-5][Listing-2-5]; weve reproduced part of it here in [Listing 19-34][Listing-19-34].
[Listing-19-34]: #Listing-19-34
<a name="Listing-19-34"></a>
```rust
# let guess = "3";
@ -211,7 +220,7 @@ let guess = match guess.trim().parse() {
The type of `guess` in this code would have to be an integer *and* a string,
and Rust requires that `guess` have only one type. So what does `continue`
return? How were we allowed to return a `u32` from one arm and have another arm
that ends with `continue` in Listing 19-34?
that ends with `continue` in [Listing 19-34][Listing-19-34]?
As you might have guessed, `continue` has a `!` value. That is, when Rust
computes the type of `guess`, it looks at both match arms, the former with a
@ -239,7 +248,7 @@ impl<T> Option<T> {
}
```
In this code, the same thing happens as in the `match` in Listing 19-34: Rust
In this code, the same thing happens as in the `match` in [Listing 19-34][Listing-19-34]: Rust
sees that `val` has the type `T` and `panic!` has the type `!`, so the result
of the overall `match` expression is `T`. This code works because `panic!`
doesnt produce a value; it ends the program. In the `None` case, we wont be
@ -347,3 +356,9 @@ Because the type might not be `Sized`, we need to use it behind some kind of
pointer. In this case, weve chosen a reference.
Next, well talk about functions and closures!
[Listing-19-23]: ch19-03-advanced-traits.html#Listing-19-23
[Listing-2-5]: ch02-00-guessing-game-tutorial.html#Listing-2-5
[Listing-19-32]: ch19-04-advanced-types.html#Listing-19-32
[Listing-19-33]: ch19-04-advanced-types.html#Listing-19-33
[Listing-19-34]: ch19-04-advanced-types.html#Listing-19-34

View File

@ -12,10 +12,13 @@ with function pointers will allow you to use functions as arguments to other
functions. Functions coerce to the type `fn` (with a lowercase f), not to be
confused with the `Fn` closure trait. The `fn` type is called a *function
pointer*. The syntax for specifying that a parameter is a function pointer is
similar to that of closures, as shown in Listing 19-35.
similar to that of closures, as shown in [Listing 19-35][Listing-19-35].
<span class="filename">Filename: src/main.rs</span>
[Listing-19-35]: #Listing-19-35
<a name="Listing-19-35"></a>
```rust
fn add_one(x: i32) -> i32 {
x + 1
@ -144,3 +147,5 @@ you to solutions.
Next, well put everything weve discussed throughout the book into practice
and do one more project!
[Listing-19-35]: ch19-05-advanced-functions-and-closures.html#Listing-19-35

View File

@ -6,7 +6,10 @@ concepts we covered in the final chapters, as well as recap some earlier
lessons.
For our final project, well make a web server that says “hello” and looks like
Figure 20-1 in a web browser.
[Figure 20-1][Figure-20-1] in a web browser.
[Figure-20-1]: #Figure-20-1
<a name="Figure-20-1"></a>
![hello from rust](img/trpl20-01.png)
@ -31,3 +34,5 @@ level of abstraction we want to work with and can go to a lower level than is
possible or practical in other languages. Well write the basic HTTP server and
thread pool manually so you can learn the general ideas and techniques behind
the crates you might use in the future.
[Figure-20-1]: ch20-00-final-project-a-web-server.html#Figure-20-1

View File

@ -31,12 +31,15 @@ $ cargo new hello --bin
$ cd hello
```
Now enter the code in Listing 20-1 in *src/main.rs* to start. This code will
Now enter the code in [Listing 20-1][Listing-20-1] in *src/main.rs* to start. This code will
listen at the address `127.0.0.1:7878` for incoming TCP streams. When it gets
an incoming stream, it will print `Connection established!`.
<span class="filename">Filename: src/main.rs</span>
[Listing-20-1]: #Listing-20-1
<a name="Listing-20-1"></a>
```rust,no_run
use std::net::TcpListener;
@ -135,10 +138,13 @@ separate the concerns of first getting a connection and then taking some action
with the connection, well start a new function for processing connections. In
this new `handle_connection` function, well read data from the TCP stream and
print it so we can see the data being sent from the browser. Change the code to
look like Listing 20-2.
look like [Listing 20-2][Listing-20-2].
<span class="filename">Filename: src/main.rs</span>
[Listing-20-2]: #Listing-20-2
<a name="Listing-20-2"></a>
```rust,no_run
use std::io::prelude::*;
use std::net::TcpStream;
@ -291,10 +297,13 @@ The status code 200 is the standard success response. The text is a tiny
successful HTTP response. Lets write this to the stream as our response to a
successful request! From the `handle_connection` function, remove the
`println!` that was printing the request data and replace it with the code in
Listing 20-3.
[Listing 20-3][Listing-20-3].
<span class="filename">Filename: src/main.rs</span>
[Listing-20-3]: #Listing-20-3
<a name="Listing-20-3"></a>
```rust
# use std::io::prelude::*;
# use std::net::TcpStream;
@ -334,11 +343,14 @@ and response!
Lets implement the functionality for returning more than a blank page. Create
a new file, *hello.html*, in the root of your project directory, not in the
*src* directory. You can input any HTML you want; Listing 20-4 shows one
*src* directory. You can input any HTML you want; [Listing 20-4][Listing-20-4] shows one
possibility.
<span class="filename">Filename: hello.html</span>
[Listing-20-4]: #Listing-20-4
<a name="Listing-20-4"></a>
```html
<!DOCTYPE html>
<html lang="en">
@ -358,11 +370,14 @@ response</span>
This is a minimal HTML5 document with a heading and some text. To return this
from the server when a request is received, well modify `handle_connection` as
shown in Listing 20-5 to read the HTML file, add it to the response as a body,
shown in [Listing 20-5][Listing-20-5] to read the HTML file, add it to the response as a body,
and send it.
<span class="filename">Filename: src/main.rs</span>
[Listing-20-5]: #Listing-20-5
<a name="Listing-20-5"></a>
```rust
# use std::io::prelude::*;
# use std::net::TcpStream;
@ -391,7 +406,7 @@ body of the response</span>
Weve added a line at the top to bring the standard librarys `File` into
scope. The code for opening a file and reading the contents should look
familiar; we used it in Chapter 12 when we read the contents of a file for our
I/O project in Listing 12-4.
I/O project in [Listing 12-4][Listing-12-4].
Next, we use `format!` to add the files contents as the body of the success
response.
@ -412,12 +427,15 @@ Right now, our web server will return the HTML in the file no matter what the
client requested. Lets add functionality to check that the browser is
requesting */* before returning the HTML file and return an error if the
browser requests anything else. For this we need to modify `handle_connection`,
as shown in Listing 20-6. This new code checks the content of the request
as shown in [Listing 20-6][Listing-20-6]. This new code checks the content of the request
received against what we know a request for */* looks like and adds `if` and
`else` blocks to treat requests differently.
<span class="filename">Filename: src/main.rs</span>
[Listing-20-6]: #Listing-20-6
<a name="Listing-20-6"></a>
```rust
# use std::io::prelude::*;
# use std::net::TcpStream;
@ -464,15 +482,18 @@ to all other requests.
Run this code now and request *127.0.0.1:7878*; you should get the HTML in
*hello.html*. If you make any other request, such as
*127.0.0.1:7878/something-else*, youll get a connection error like those you
saw when running the code in Listing 20-1 and Listing 20-2.
saw when running the code in [Listing 20-1][Listing-20-1] and [Listing 20-2][Listing-20-2].
Now lets add the code in Listing 20-7 to the `else` block to return a response
Now lets add the code in [Listing 20-7][Listing-20-7] to the `else` block to return a response
with the status code 404, which signals that the content for the request was
not found. Well also return some HTML for a page to render in the browser
indicating the response to the end user.
<span class="filename">Filename: src/main.rs</span>
[Listing-20-7]: #Listing-20-7
<a name="Listing-20-7"></a>
```rust
# use std::io::prelude::*;
# use std::net::TcpStream;
@ -503,10 +524,13 @@ Here, our response has a status line with status code 404 and the reason
phrase `NOT FOUND`. Were still not returning headers, and the body of the
response will be the HTML in the file *404.html*. Youll need to create a
*404.html* file next to *hello.html* for the error page; again feel free to use
any HTML you want or use the example HTML in Listing 20-8.
any HTML you want or use the example HTML in [Listing 20-8][Listing-20-8].
<span class="filename">Filename: 404.html</span>
[Listing-20-8]: #Listing-20-8
<a name="Listing-20-8"></a>
```html
<!DOCTYPE html>
<html lang="en">
@ -536,11 +560,14 @@ differences are the status line and the filename. Lets make the code more
concise by pulling out those differences into separate `if` and `else` lines
that will assign the values of the status line and the filename to variables;
we can then use those variables unconditionally in the code to read the file
and write the response. Listing 20-9 shows the resulting code after replacing
and write the response. [Listing 20-9][Listing-20-9] shows the resulting code after replacing
the large `if` and `else` blocks.
<span class="filename">Filename: src/main.rs</span>
[Listing-20-9]: #Listing-20-9
<a name="Listing-20-9"></a>
```rust
# use std::io::prelude::*;
# use std::net::TcpStream;
@ -584,8 +611,8 @@ The previously duplicated code is now outside the `if` and `else` blocks and
uses the `status_line` and `filename` variables. This makes it easier to see
the difference between the two cases, and it means we have only one place to
update the code if we want to change how the file reading and response writing
work. The behavior of the code in Listing 20-9 will be the same as that in
Listing 20-8.
work. The behavior of the code in [Listing 20-9][Listing-20-9] will be the same as that in
[Listing 20-8][Listing-20-8].
Awesome! We now have a simple web server in approximately 40 lines of Rust code
that responds to one request with a page of content and responds to all other
@ -595,3 +622,14 @@ Currently, our server runs in a single thread, meaning it can only serve one
request at a time. Lets examine how that can be a problem by simulating some
slow requests. Then well fix it so our server can handle multiple requests at
once.
[Listing-12-4]: ch12-02-reading-a-file.html#Listing-12-4
[Listing-20-1]: ch20-01-single-threaded.html#Listing-20-1
[Listing-20-2]: ch20-01-single-threaded.html#Listing-20-2
[Listing-20-3]: ch20-01-single-threaded.html#Listing-20-3
[Listing-20-4]: ch20-01-single-threaded.html#Listing-20-4
[Listing-20-5]: ch20-01-single-threaded.html#Listing-20-5
[Listing-20-6]: ch20-01-single-threaded.html#Listing-20-6
[Listing-20-7]: ch20-01-single-threaded.html#Listing-20-7
[Listing-20-8]: ch20-01-single-threaded.html#Listing-20-8
[Listing-20-9]: ch20-01-single-threaded.html#Listing-20-9

View File

@ -11,12 +11,15 @@ this, but first, well look at the problem in action.
### Simulating a Slow Request in the Current Server Implementation
Well look at how a slow-processing request can affect other requests made to
our current server implementation. Listing 20-10 implements handling a request
our current server implementation. [Listing 20-10][Listing-20-10] implements handling a request
to */sleep* with a simulated slow response that will cause the server to sleep
for 5 seconds before responding.
<span class="filename">Filename: src/main.rs</span>
[Listing-20-10]: #Listing-20-10
<a name="Listing-20-10"></a>
```rust
use std::thread;
use std::time::Duration;
@ -118,11 +121,14 @@ what we should change next to get the code to work.
First, lets explore how our code might look if it did create a new thread for
every connection. As mentioned earlier, this isnt our final plan due to the
problems with potentially spawning an unlimited number of threads, but it is a
starting point. Listing 20-11 shows the changes to make to `main` to spawn a
starting point. [Listing 20-11][Listing-20-11] shows the changes to make to `main` to spawn a
new thread to handle each stream within the `for` loop.
<span class="filename">Filename: src/main.rs</span>
[Listing-20-11]: #Listing-20-11
<a name="Listing-20-11"></a>
```rust,no_run
# use std::thread;
# use std::io::prelude::*;
@ -157,11 +163,14 @@ new threads without any limit.
We want our thread pool to work in a similar, familiar way so switching from
threads to a thread pool doesnt require large changes to the code that uses
our API. Listing 20-12 shows the hypothetical interface for a `ThreadPool`
our API. [Listing 20-12][Listing-20-12] shows the hypothetical interface for a `ThreadPool`
struct we want to use instead of `thread::spawn`.
<span class="filename">Filename: src/main.rs</span>
[Listing-20-12]: #Listing-20-12
<a name="Listing-20-12"></a>
```rust,no_run
# use std::thread;
# use std::io::prelude::*;
@ -200,7 +209,7 @@ compile, but well try so the compiler can guide us in how to fix it.
#### Building the `ThreadPool` Struct Using Compiler Driven Development
Make the changes in Listing 20-12 to *src/main.rs*, and then lets use the
Make the changes in [Listing 20-12][Listing-20-12] to *src/main.rs*, and then lets use the
compiler errors from `cargo check` to drive our development. Here is the first
error we get:
@ -411,10 +420,13 @@ negative number of threads makes no sense. However, a pool with zero threads
also makes no sense, yet zero is a perfectly valid `usize`. Well add code to
check that `size` is greater than zero before we return a `ThreadPool` instance
and have the program panic if it receives a zero by using the `assert!` macro,
as shown in Listing 20-13.
as shown in [Listing 20-13][Listing-20-13].
<span class="filename">Filename: src/lib.rs</span>
[Listing-20-13]: #Listing-20-13
<a name="Listing-20-13"></a>
```rust
# pub struct ThreadPool;
impl ThreadPool {
@ -445,8 +457,8 @@ Try running `cargo doc --open` and clicking the `ThreadPool` struct to see what
the generated docs for `new` look like!
Instead of adding the `assert!` macro as weve done here, we could make `new`
return a `Result` like we did with `Config::new` in the I/O project in Listing
12-9. But weve decided in this case that trying to create a thread pool
return a `Result` like we did with `Config::new` in the I/O project in [Listing 12-9][Listing-12-9].
But weve decided in this case that trying to create a thread pool
without any threads should be an unrecoverable error. If youre feeling
ambitious, try to write a version of `new` with the following signature to
compare both versions:
@ -474,7 +486,7 @@ closure returns. Lets try using `JoinHandle` too and see what happens. In our
case, the closures were passing to the thread pool will handle the connection
and not return anything, so `T` will be the unit type `()`.
The code in Listing 20-14 will compile but doesnt create any threads yet.
The code in [Listing 20-14][Listing-20-14] will compile but doesnt create any threads yet.
Weve changed the definition of `ThreadPool` to hold a vector of
`thread::JoinHandle<()>` instances, initialized the vector with a capacity of
`size`, set up a `for` loop that will run some code to create the threads, and
@ -482,6 +494,9 @@ returned a `ThreadPool` instance containing them.
<span class="filename">Filename: src/lib.rs</span>
[Listing-20-14]: #Listing-20-14
<a name="Listing-20-14"></a>
```rust,ignore
use std::thread;
@ -529,7 +544,7 @@ succeed.
#### A `Worker` Struct Responsible for Sending Code from the `ThreadPool` to a Thread
We left a comment in the `for` loop in Listing 20-14 regarding the creation of
We left a comment in the `for` loop in [Listing 20-14][Listing-20-14] regarding the creation of
threads. Here, well look at how we actually create threads. The standard
library provides `thread::spawn` as a way to create threads, and
`thread::spawn` expects to get some code the thread should run as soon as the
@ -565,12 +580,15 @@ Well implement the code that sends the closure to the thread after we have
a new `Worker` with that `id`, and store the worker in the vector.
If youre up for a challenge, try implementing these changes on your own before
looking at the code in Listing 20-15.
looking at the code in [Listing 20-15][Listing-20-15].
Ready? Here is Listing 20-15 with one way to make the preceding modifications.
Ready? Here is [Listing 20-15][Listing-20-15] with one way to make the preceding modifications.
<span class="filename">Filename: src/lib.rs</span>
[Listing-20-15]: #Listing-20-15
<a name="Listing-20-15"></a>
```rust
use std::thread;
@ -658,12 +676,15 @@ Here is the plan:
and execute the closures of any jobs it receives.
Lets start by creating a channel in `ThreadPool::new` and holding the sending
side in the `ThreadPool` instance, as shown in Listing 20-16. The `Job` struct
side in the `ThreadPool` instance, as shown in [Listing 20-16][Listing-20-16]. The `Job` struct
doesnt hold anything for now but will be the type of item were sending down
the channel.
<span class="filename">Filename: src/lib.rs</span>
[Listing-20-16]: #Listing-20-16
<a name="Listing-20-16"></a>
```rust
# use std::thread;
// --snip--
@ -723,10 +744,13 @@ sending end. This will successfully compile, still with warnings.
Lets try passing a receiving end of the channel into each worker as the thread
pool creates the channel. We know we want to use the receiving end in the
thread that the workers spawn, so well reference the `receiver` parameter in
the closure. The code in Listing 20-17 wont quite compile yet.
the closure. The code in [Listing 20-17][Listing-20-17] wont quite compile yet.
<span class="filename">Filename: src/lib.rs</span>
[Listing-20-17]: #Listing-20-17
<a name="Listing-20-17"></a>
```rust,ignore
impl ThreadPool {
// --snip--
@ -802,10 +826,13 @@ Recall the thread-safe smart pointers discussed in Chapter 16: to share
ownership across multiple threads and allow the threads to mutate the value, we
need to use `Arc<Mutex<T>>`. The `Arc` type will let multiple workers own the
receiver, and `Mutex` will ensure that only one worker gets a job from the
receiver at a time. Listing 20-18 shows the changes we need to make.
receiver at a time. [Listing 20-18][Listing-20-18] shows the changes we need to make.
<span class="filename">Filename: src/lib.rs</span>
[Listing-20-18]: #Listing-20-18
<a name="Listing-20-18"></a>
```rust
# use std::thread;
# use std::sync::mpsc;
@ -878,10 +905,13 @@ Lets finally implement the `execute` method on `ThreadPool`. Well also cha
`Job` from a struct to a type alias for a trait object that holds the type of
closure that `execute` receives. As discussed in the “Creating Type Synonyms
with Type Aliases” section of Chapter 19, type aliases allow us to make long
types shorter. Look at Listing 20-19.
types shorter. Look at [Listing 20-19][Listing-20-19].
<span class="filename">Filename: src/lib.rs</span>
[Listing-20-19]: #Listing-20-19
<a name="Listing-20-19"></a>
```rust
// --snip--
# pub struct ThreadPool {
@ -925,10 +955,13 @@ But were not quite done yet! In the worker, our closure being passed to
`thread::spawn` still only *references* the receiving end of the channel.
Instead, we need the closure to loop forever, asking the receiving end of the
channel for a job and running the job when it gets one. Lets make the change
shown in Listing 20-20 to `Worker::new`.
shown in [Listing 20-20][Listing-20-20] to `Worker::new`.
<span class="filename">Filename: src/lib.rs</span>
[Listing-20-20]: #Listing-20-20
<a name="Listing-20-20"></a>
```rust,ignore
// --snip--
@ -994,7 +1027,7 @@ the value inside the `Box<T>` will be: recall in Chapter 15 that we used
`Box<T>` precisely because we had something of an unknown size that we wanted
to store in a `Box<T>` to get a value of a known size.
As you saw in Listing 17-15, we can write methods that use the syntax `self:
As you saw in [Listing 17-15][Listing-17-15], we can write methods that use the syntax `self:
Box<Self>`, which allows the method to take ownership of a `Self` value stored
in a `Box<T>`. Thats exactly what we want to do here, but unfortunately Rust
wont let us: the part of Rust that implements behavior when a closure is
@ -1003,7 +1036,7 @@ understand that it could use `self: Box<Self>` in this situation to take
ownership of the closure and move the closure out of the `Box<T>`.
Rust is still a work in progress with places where the compiler could be
improved, but in the future, the code in Listing 20-20 should work just fine.
improved, but in the future, the code in [Listing 20-20][Listing-20-20] should work just fine.
People just like you are working to fix this and other issues! After youve
finished this book, we would love for you to join in.
@ -1014,10 +1047,13 @@ we can call it. This involves defining a new trait `FnBox` with the method
`call_box` that will use `self: Box<Self>` in its signature, defining `FnBox`
for any type that implements `FnOnce()`, changing our type alias to use the new
trait, and changing `Worker` to use the `call_box` method. These changes are
shown in Listing 20-21.
shown in [Listing 20-21][Listing-20-21].
<span class="filename">Filename: src/lib.rs</span>
[Listing-20-21]: #Listing-20-21
<a name="Listing-20-21"></a>
```rust,ignore
trait FnBox {
fn call_box(self: Box<Self>);
@ -1127,10 +1163,13 @@ overloaded if the server receives a lot of requests. If we make a request to
thread run them.
After learning about the `while let` loop in Chapter 18, you might be wondering
why we didnt write the worker thread code as shown in Listing 20-22.
why we didnt write the worker thread code as shown in [Listing 20-22][Listing-20-22].
<span class="filename">Filename: src/lib.rs</span>
[Listing-20-22]: #Listing-20-22
<a name="Listing-20-22"></a>
```rust,ignore
// --snip--
@ -1173,3 +1212,19 @@ rather than outside it, the `MutexGuard` returned from the `lock` method is
dropped as soon as the `let job` statement ends. This ensures that the lock is
held during the call to `recv`, but it is released before the call to
`job.call_box()`, allowing multiple requests to be serviced concurrently.
[Listing-17-15]: ch17-03-oo-design-patterns.html#Listing-17-15
[Listing-20-10]: ch20-02-multithreaded.html#Listing-20-10
[Listing-20-11]: ch20-02-multithreaded.html#Listing-20-11
[Listing-20-12]: ch20-02-multithreaded.html#Listing-20-12
[Listing-20-13]: ch20-02-multithreaded.html#Listing-20-13
[Listing-20-14]: ch20-02-multithreaded.html#Listing-20-14
[Listing-20-15]: ch20-02-multithreaded.html#Listing-20-15
[Listing-20-16]: ch20-02-multithreaded.html#Listing-20-16
[Listing-20-17]: ch20-02-multithreaded.html#Listing-20-17
[Listing-20-18]: ch20-02-multithreaded.html#Listing-20-18
[Listing-20-19]: ch20-02-multithreaded.html#Listing-20-19
[Listing-20-20]: ch20-02-multithreaded.html#Listing-20-20
[Listing-20-21]: ch20-02-multithreaded.html#Listing-20-21
[Listing-20-22]: ch20-02-multithreaded.html#Listing-20-22
[Listing-12-9]: ch12-03-improving-error-handling-and-modularity.html#Listing-12-9

View File

@ -1,6 +1,6 @@
## Graceful Shutdown and Cleanup
The code in Listing 20-21 is responding to requests asynchronously through the
The code in [Listing 20-21][Listing-20-21] is responding to requests asynchronously through the
use of a thread pool, as we intended. We get some warnings about the `workers`,
`id`, and `thread` fields that were not using in a direct way that reminds us
were not cleaning up anything. When we use the less elegant <span
@ -18,11 +18,14 @@ accept only two requests before gracefully shutting down its thread pool.
Lets start with implementing `Drop` on our thread pool. When the pool is
dropped, our threads should all join to make sure they finish their work.
Listing 20-23 shows a first attempt at a `Drop` implementation; this code wont
[Listing 20-23][Listing-20-23] shows a first attempt at a `Drop` implementation; this code wont
quite work yet.
<span class="filename">Filename: src/lib.rs</span>
[Listing-20-23]: #Listing-20-23
<a name="Listing-20-23"></a>
```rust,ignore
impl Drop for ThreadPool {
fn drop(&mut self) {
@ -58,8 +61,8 @@ error[E0507]: cannot move out of borrowed content
The error tells us we cant call `join` because we only have a mutable borrow
of each `worker` and `join` takes ownership of its argument. To solve this
issue, we need to move the thread out of the `Worker` instance that owns
`thread` so `join` can consume the thread. We did this in Listing 17-15: if
`Worker` holds an `Option<thread::JoinHandle<()>>` instead, we can call the
`thread` so `join` can consume the thread. We did this in [Listing 17-15][Listing-17-15]: if
`Worker` holds an `Option<thread::JoinHandle<()>` instead, we can call the
`take` method on the `Option` to move the value out of the `Some` variant and
leave a `None` variant in its place. In other words, a `Worker` that is running
will have a `Some` variant in `thread`, and when we want to clean up a
@ -178,10 +181,13 @@ thread should run, or it will be a `Terminate` variant that will cause the
thread to exit its loop and stop.
We need to adjust the channel to use values of type `Message` rather than type
`Job`, as shown in Listing 20-24.
`Job`, as shown in [Listing 20-24][Listing-20-24].
<span class="filename">Filename: src/lib.rs</span>
[Listing-20-24]: #Listing-20-24
<a name="Listing-20-24"></a>
```rust,ignore
pub struct ThreadPool {
workers: Vec<Worker>,
@ -248,12 +254,15 @@ received, and the thread will break out of the loop if the `Terminate` variant
is received.
With these changes, the code will compile and continue to function in the same
way as it did after Listing 20-21. But well get a warning because we arent
way as it did after [Listing 20-21][Listing-20-21]. But well get a warning because we arent
creating any messages of the `Terminate` variety. Lets fix this warning by
changing our `Drop` implementation to look like Listing 20-25.
changing our `Drop` implementation to look like [Listing 20-25][Listing-20-25].
<span class="filename">Filename: src/lib.rs</span>
[Listing-20-25]: #Listing-20-25
<a name="Listing-20-25"></a>
```rust,ignore
impl Drop for ThreadPool {
fn drop(&mut self) {
@ -302,10 +311,13 @@ messages as there are workers, each worker will receive a terminate message
before `join` is called on its thread.
To see this code in action, lets modify `main` to accept only two requests
before gracefully shutting down the server, as shown in Listing 20-26.
before gracefully shutting down the server, as shown in [Listing 20-26][Listing-20-26].
<span class="filename">Filename: src/bin/main.rs</span>
[Listing-20-26]: #Listing-20-26
<a name="Listing-20-26"></a>
```rust,ignore
fn main() {
let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
@ -577,3 +589,10 @@ joining us on this tour of Rust. Youre now ready to implement your own Rust
projects and help with other peoples projects. Keep in mind that there is a
welcoming community of other Rustaceans who would love to help you with any
challenges you encounter on your Rust journey.
[Listing-17-15]: ch17-03-oo-design-patterns.html#Listing-17-15
[Listing-20-23]: ch20-03-graceful-shutdown-and-cleanup.html#Listing-20-23
[Listing-20-24]: ch20-03-graceful-shutdown-and-cleanup.html#Listing-20-24
[Listing-20-25]: ch20-03-graceful-shutdown-and-cleanup.html#Listing-20-25
[Listing-20-26]: ch20-03-graceful-shutdown-and-cleanup.html#Listing-20-26
[Listing-20-21]: ch20-02-multithreaded.html#Listing-20-21