mirror of https://github.com/rust-lang/book
Messy snapshot of chapter 13 after copyedit check
This commit is contained in:
parent
b2bb43de0e
commit
785a34359a
2
TODO.md
2
TODO.md
|
@ -1,6 +1,6 @@
|
||||||
# In each chapter
|
# In each chapter
|
||||||
|
|
||||||
- [x] Manual regeneration
|
- [ ] Manual regeneration
|
||||||
- [ ] Check for upstream changes from last snapshot
|
- [ ] Check for upstream changes from last snapshot
|
||||||
- [ ] Propagate updated output to docx
|
- [ ] Propagate updated output to docx
|
||||||
- [ ] Extract docx and check diff
|
- [ ] Extract docx and check diff
|
||||||
|
|
|
@ -114,7 +114,7 @@ impl Inventory {
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
user_preference: Option<ShirtColor>
|
user_preference: Option<ShirtColor>,
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -226,7 +226,7 @@ fn main() {
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
ShirtColor::Blue
|
ShirtColor::Blue,
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -321,29 +321,13 @@ calls the closure and returns the value returned by the closure.
|
||||||
|
|
||||||
We specify the closure expression `|| self.most_stocked()` as the argument to
|
We specify the closure expression `|| self.most_stocked()` as the argument to
|
||||||
`unwrap_or_else`. This is a closure that takes no parameters itself (if the
|
`unwrap_or_else`. This is a closure that takes no parameters itself (if the
|
||||||
closure had parameters, they would appear between the two vertical bars). The
|
closure had parameters, they would appear between the two vertical pipes). The
|
||||||
body of the closure calls `self.most_stocked()`. We’re defining the closure
|
body of the closure calls `self.most_stocked()`. We’re defining the closure
|
||||||
here, and the implementation of `unwrap_or_else` will evaluate the closure
|
here, and the implementation of `unwrap_or_else` will evaluate the closure
|
||||||
later if the result is needed.
|
later if the result is needed.
|
||||||
|
|
||||||
Running this code prints the following:
|
Running this code prints the following:
|
||||||
|
|
||||||
```
|
|
||||||
$ cargo run
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Compiling shirt-company v0.1.0 (file:///projects/shirt-company)
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Finished dev [unoptimized + debuginfo] target(s) in 0.27s
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Running `target/debug/shirt-company`
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
```
|
||||||
The user with preference Some(Red) gets Red
|
The user with preference Some(Red) gets Red
|
||||||
```
|
```
|
||||||
|
@ -491,6 +475,9 @@ error[E0308]: mismatched types
|
||||||
|
|
||||||
```
|
```
|
||||||
| ^- help: try using a conversion method:
|
| ^- help: try using a conversion method:
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
`.to_string()`
|
`.to_string()`
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -811,8 +798,8 @@ Using `FnOnce` in the trait bound expresses the constraint that
|
||||||
`unwrap_or_else` is only going to call `f` at most one time. In the body of
|
`unwrap_or_else` is only going to call `f` at most one time. In the body of
|
||||||
`unwrap_or_else`, we can see that if the `Option` is `Some`, `f` won’t be
|
`unwrap_or_else`, we can see that if the `Option` is `Some`, `f` won’t be
|
||||||
called. If the `Option` is `None`, `f` will be called once. Because all
|
called. If the `Option` is `None`, `f` will be called once. Because all
|
||||||
closures implement `FnOnce`, `unwrap_or_else` accepts the most different kinds
|
closures implement `FnOnce`, `unwrap_or_else` accepts the largest variety of
|
||||||
of closures and is as flexible as it can be.
|
closures and is as flexible as it can be.
|
||||||
|
|
||||||
> NoteFunctions can implement all three of the `Fn` traits too. If what we want
|
> NoteFunctions can implement all three of the `Fn` traits too. If what we want
|
||||||
to do doesn’t require capturing a value from the environment, we can use the
|
to do doesn’t require capturing a value from the environment, we can use the
|
||||||
|
@ -968,23 +955,7 @@ compiler won’t let us use this closure with `sort_by_key`.
|
||||||
Filename: src/main.rs
|
Filename: src/main.rs
|
||||||
|
|
||||||
```
|
```
|
||||||
#[derive(Debug)]
|
--snip--
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
struct Rectangle {
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
width: u32,
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
height: u32,
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -1071,6 +1042,9 @@ implement `FnMut`:
|
||||||
|
|
||||||
```
|
```
|
||||||
error[E0507]: cannot move out of `value`, a captured variable in an `FnMut`
|
error[E0507]: cannot move out of `value`, a captured variable in an `FnMut`
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
closure
|
closure
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1137,23 +1111,7 @@ the `num_sort_operations` counter and can therefore be called more than once.
|
||||||
Filename: src/main.rs
|
Filename: src/main.rs
|
||||||
|
|
||||||
```
|
```
|
||||||
#[derive(Debug)]
|
--snip--
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
struct Rectangle {
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
width: u32,
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
height: u32,
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -1165,23 +1123,7 @@ fn main() {
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
let mut list = [
|
--snip--
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Rectangle { width: 10, height: 1 },
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Rectangle { width: 3, height: 5 },
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
Rectangle { width: 7, height: 12 },
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
];
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -1209,7 +1151,19 @@ fn main() {
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
println!("{:#?}, sorted in {num_sort_operations} operations", list);
|
println!(
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
"{:#?}, sorted in {num_sort_operations} operations",
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
list
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -1282,7 +1236,7 @@ for val in v1_iter {
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
println!("Got: {}", val);
|
println!("Got: {val}");
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -1422,12 +1376,12 @@ trait. Some of these methods call the `next` method in their definition, which
|
||||||
is why you’re required to implement the `next` method when implementing the
|
is why you’re required to implement the `next` method when implementing the
|
||||||
`Iterator` trait.
|
`Iterator` trait.
|
||||||
|
|
||||||
Methods that call `next` are called *consuming adaptors* because calling them
|
Methods that call `next` are called *consuming adapt**e**rs* because calling
|
||||||
uses up the iterator. One example is the `sum` method, which takes ownership of
|
them uses up the iterator. One example is the `sum` method, which takes
|
||||||
the iterator and iterates through the items by repeatedly calling `next`, thus
|
ownership of the iterator and iterates through the items by repeatedly calling
|
||||||
consuming the iterator. As it iterates through, it adds each item to a running
|
`next`, thus consuming the iterator. As it iterates through, it adds each item
|
||||||
total and returns the total when iteration is complete. Listing 13-13 has a
|
to a running total and returns the total when iteration is complete. Listing
|
||||||
test illustrating a use of the `sum` method.
|
13-13 has a test illustrating a use of the `sum` method.
|
||||||
|
|
||||||
Filename: src/lib.rs
|
Filename: src/lib.rs
|
||||||
|
|
||||||
|
@ -1478,11 +1432,11 @@ ownership of the iterator we call it on.
|
||||||
|
|
||||||
### Methods That Produce Other Iterators
|
### Methods That Produce Other Iterators
|
||||||
|
|
||||||
*Iterator adaptors* are methods defined on the `Iterator` trait that don’t
|
*Iterator adapt**e**rs* are methods defined on the `Iterator` trait that don’t
|
||||||
consume the iterator. Instead, they produce different iterators by changing
|
consume the iterator. Instead, they produce different iterators by changing
|
||||||
some aspect of the original iterator.
|
some aspect of the original iterator.
|
||||||
|
|
||||||
Listing 13-14 shows an example of calling the iterator adaptor method `map`,
|
Listing 13-14 shows an example of calling the iterator adapter method `map`,
|
||||||
which takes a closure to call on each item as the items are iterated through.
|
which takes a closure to call on each item as the items are iterated through.
|
||||||
The `map` method returns a new iterator that produces the modified items. The
|
The `map` method returns a new iterator that produces the modified items. The
|
||||||
closure here creates a new iterator in which each item from the vector will be
|
closure here creates a new iterator in which each item from the vector will be
|
||||||
|
@ -1502,7 +1456,7 @@ let v1: Vec<i32> = vec![1, 2, 3];
|
||||||
v1.iter().map(|x| x + 1);
|
v1.iter().map(|x| x + 1);
|
||||||
```
|
```
|
||||||
|
|
||||||
Calling the iterator adaptor `map` to create a new iterator
|
Calling the iterator adapter `map` to create a new iterator
|
||||||
|
|
||||||
However, this code produces a warning:
|
However, this code produces a warning:
|
||||||
|
|
||||||
|
@ -1539,7 +1493,7 @@ warning: unused `Map` that must be used
|
||||||
```
|
```
|
||||||
|
|
||||||
The code in Listing 13-14 doesn’t do anything; the closure we’ve specified
|
The code in Listing 13-14 doesn’t do anything; the closure we’ve specified
|
||||||
never gets called. The warning reminds us why: iterator adaptors are lazy, and
|
never gets called. The warning reminds us why: iterator adapters are lazy, and
|
||||||
we need to consume the iterator here.
|
we need to consume the iterator here.
|
||||||
|
|
||||||
To fix this warning and consume the iterator, we’ll use the `collect` method,
|
To fix this warning and consume the iterator, we’ll use the `collect` method,
|
||||||
|
@ -1580,9 +1534,9 @@ on each item. This is a great example of how closures let you customize some
|
||||||
behavior while reusing the iteration behavior that the `Iterator` trait
|
behavior while reusing the iteration behavior that the `Iterator` trait
|
||||||
provides.
|
provides.
|
||||||
|
|
||||||
You can chain multiple calls to iterator adaptors to perform complex actions in
|
You can chain multiple calls to iterator adapters to perform complex actions in
|
||||||
a readable way. But because all iterators are lazy, you have to call one of the
|
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.
|
consuming adapter methods to get results from calls to iterator adapters.
|
||||||
|
|
||||||
### Using Closures That Capture Their Environment
|
### Using Closures That Capture Their Environment
|
||||||
|
|
||||||
|
@ -1834,7 +1788,15 @@ impl Config {
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
pub fn build(args: &[String]) -> Result<Config, &'static str> {
|
pub fn build(
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
args: &[String]
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
) -> Result<Config, &'static str> {
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -1978,19 +1940,23 @@ fn main() {
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
let config = Config::build(env::args()).unwrap_or_else(|err| {
|
let config =
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
eprintln!("Problem parsing arguments: {err}");
|
Config::build(env::args()).unwrap_or_else(|err| {
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
process::exit(1);
|
eprintln!("Problem parsing arguments: {err}");
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
});
|
process::exit(1);
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -2173,7 +2139,7 @@ value we want to put in the `query` field of `Config`. If `next` returns
|
||||||
not enough arguments were given and we return early with an `Err` value. We do
|
not enough arguments were given and we return early with an `Err` value. We do
|
||||||
the same thing for the `filename` value.
|
the same thing for the `filename` value.
|
||||||
|
|
||||||
### Making Code Clearer with Iterator Adaptors
|
### Making Code Clearer with Iterator Adapters
|
||||||
|
|
||||||
We can also take advantage of iterators in the `search` function in our I/O
|
We can also take advantage of iterators in the `search` function in our I/O
|
||||||
project, which is reproduced here in Listing 13-21 as it was in Listing 12-19.
|
project, which is reproduced here in Listing 13-21 as it was in Listing 12-19.
|
||||||
|
@ -2226,7 +2192,7 @@ pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
|
||||||
|
|
||||||
The implementation of the `search` function from Listing 12-19
|
The implementation of the `search` function from Listing 12-19
|
||||||
|
|
||||||
We can write this code in a more concise way using iterator adaptor methods.
|
We can write this code in a more concise way using iterator adapter methods.
|
||||||
Doing so also lets us avoid having a mutable intermediate `results` vector. The
|
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
|
functional programming style prefers to minimize the amount of mutable state to
|
||||||
make code clearer. Removing the mutable state might enable a future enhancement
|
make code clearer. Removing the mutable state might enable a future enhancement
|
||||||
|
@ -2259,11 +2225,11 @@ pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Using iterator adaptor methods in the implementation of the `search` function
|
Using iterator adapter methods in the implementation of the `search` function
|
||||||
|
|
||||||
Recall that the purpose of the `search` function is to return all lines in
|
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
|
`contents` that contain the `query`. Similar to the `filter` example in Listing
|
||||||
13-16, this code uses the `filter` adaptor to keep only the lines for which
|
13-16, this code uses the `filter` adapter to keep only the lines for which
|
||||||
`line.contains(query)` returns `true`. We then collect the matching lines into
|
`line.contains(query)` returns `true`. We then collect the matching lines into
|
||||||
another vector with `collect`. Much simpler! Feel free to make the same change
|
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.
|
to use iterator methods in the `search_case_insensitive` function as well.
|
||||||
|
@ -2274,7 +2240,7 @@ The next logical question is which style you should choose in your own code and
|
||||||
why: the original implementation in Listing 13-21 or the version using
|
why: the original implementation in Listing 13-21 or the version using
|
||||||
iterators in Listing 13-22. Most Rust programmers prefer to use the iterator
|
iterators in Listing 13-22. Most Rust programmers prefer to use the iterator
|
||||||
style. It’s a bit tougher to get the hang of at first, but once you get a feel
|
style. It’s 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
|
for the various iterator adapters and what they do, iterators can be easier to
|
||||||
understand. Instead of fiddling with the various bits of looping and building
|
understand. Instead of fiddling with the various bits of looping and building
|
||||||
new vectors, the code focuses on the high-level objective of the loop. This
|
new vectors, the code focuses on the high-level objective of the loop. This
|
||||||
abstracts away some of the commonplace code so it’s easier to see the concepts
|
abstracts away some of the commonplace code so it’s easier to see the concepts
|
||||||
|
@ -2385,7 +2351,7 @@ multiplies the values together, sums all the results, and shifts the bits in
|
||||||
the sum `qlp_shift` bits to the right.
|
the sum `qlp_shift` bits to the right.
|
||||||
|
|
||||||
Calculations in applications like audio decoders often prioritize performance
|
Calculations in applications like audio decoders often prioritize performance
|
||||||
most highly. Here, we’re creating an iterator, using two adaptors, and then
|
most highly. Here, we’re creating an iterator, using two adapters, and then
|
||||||
consuming the value. What assembly code would this Rust code compile to? Well,
|
consuming the value. What assembly code would this Rust code compile to? Well,
|
||||||
as of this writing, it compiles down to the same assembly you’d write by hand.
|
as of this writing, it compiles down to the same assembly you’d write by hand.
|
||||||
There’s no loop at all corresponding to the iteration over the values in
|
There’s no loop at all corresponding to the iteration over the values in
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue