Skip to content

Commit

Permalink
[wip] More changes caught during ↔ backports
Browse files Browse the repository at this point in the history
  • Loading branch information
chriskrycho committed Mar 4, 2025
1 parent 77111e1 commit 349e17c
Show file tree
Hide file tree
Showing 35 changed files with 364 additions and 390 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[workspace]
resolver = "2"
resolver = "3"
members = ["adder", "add_one"]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[workspace]
resolver = "2"
resolver = "3"
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[workspace]
resolver = "2"
resolver = "3"
members = ["adder", "add_one"]
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[workspace]
resolver = "2"
resolver = "3"
members = ["adder", "add_one"]
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[workspace]
resolver = "2"
resolver = "3"
members = ["adder", "add_one"]
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[workspace]
resolver = "2"
resolver = "3"
members = ["adder"]
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[workspace]
resolver = "2"
resolver = "3"
members = [ "add_one","adder"]
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[workspace]
resolver = "2"
resolver = "3"
members = ["adder", "add_one"]
4 changes: 2 additions & 2 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@

- [Smart Pointers](ch15-00-smart-pointers.md)
- [Using `Box<T>` to Point to Data on the Heap](ch15-01-box.md)
- [Treating Smart Pointers Like Regular References with the `Deref` Trait](ch15-02-deref.md)
- [Treating Smart Pointers Like Regular References with `Deref`](ch15-02-deref.md)
- [Running Code on Cleanup with the `Drop` Trait](ch15-03-drop.md)
- [`Rc<T>`, the Reference Counted Smart Pointer](ch15-04-rc.md)
- [`RefCell<T>` and the Interior Mutability Pattern](ch15-05-interior-mutability.md)
Expand All @@ -99,7 +99,7 @@
- [Using Threads to Run Code Simultaneously](ch16-01-threads.md)
- [Using Message Passing to Transfer Data Between Threads](ch16-02-message-passing.md)
- [Shared-State Concurrency](ch16-03-shared-state.md)
- [Extensible Concurrency with the `Sync` and `Send` Traits](ch16-04-extensible-concurrency-sync-and-send.md)
- [Extensible Concurrency with the `Send` and `Sync` Traits](ch16-04-extensible-concurrency-sync-and-send.md)

- [Fundamentals of Asynchronous Programming: Async, Await, Futures, and Streams](ch17-00-async-await.md)
- [Futures and the Async Syntax](ch17-01-futures-and-syntax.md)
Expand Down
4 changes: 2 additions & 2 deletions src/ch12-05-working-with-environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ they’ll be the same case when we check whether the line contains the query.
</Listing>

First we lowercase the `query` string and store it in a new variable with the
same name, shadowing the original. Calling `to_lowercase` on the query is
necessary so that no matter whether the user’s query is `"rust"`, `"RUST"`,
same name, shadowing the original `query`. Calling `to_lowercase` on the query
is necessary so that no matter whether the user’s query is `"rust"`, `"RUST"`,
`"Rust"`, or `"rUsT"`, we’ll treat the query as if it were `"rust"` and be
insensitive to the case. While `to_lowercase` will handle basic Unicode, it
won’t be 100% accurate. If we were writing a real application, we’d want to do a
Expand Down
2 changes: 1 addition & 1 deletion src/ch13-00-functional-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ More specifically, we’ll cover:
- _Closures_, a function-like construct you can store in a variable
- _Iterators_, a way of processing a series of elements
- How to use closures and iterators to improve the I/O project in Chapter 12
- The performance of closures and iterators (Spoiler alert: they’re faster than
- The performance of closures and iterators (spoiler alert: they’re faster than
you might think!)

We’ve already covered some other Rust features, such as pattern matching and
Expand Down
23 changes: 11 additions & 12 deletions src/ch13-01-closures.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<a id="closures-anonymous-functions-that-can-capture-their-environment"></a>

## Closures: Anonymous Functions that Capture Their Environment
## Closures: Anonymous Functions That Capture Their Environment

Rust’s closures are anonymous functions you can save in a variable or pass as
arguments to other functions. You can create the closure in one place and then
Expand Down Expand Up @@ -50,7 +50,7 @@ to distribute for this limited-edition promotion. We call the `giveaway` method
for a user with a preference for a red shirt and a user without any preference.

Again, this code could be implemented in many ways, and here, to focus on
closures, we’ve stuck to concepts you’ve already learned except for the body of
closures, we’ve stuck to concepts you’ve already learned, except for the body of
the `giveaway` method that uses a closure. In the `giveaway` method, we get the
user preference as a parameter of type `Option<ShirtColor>` and call the
`unwrap_or_else` method on `user_preference`. The [`unwrap_or_else` method on
Expand Down Expand Up @@ -283,9 +283,9 @@ implement one, two, or all three of these `Fn` traits, in an additive fashion,
depending on how the closure’s body handles the values:

1. `FnOnce` applies to closures that can be called once. All closures implement
at least this trait, because all closures can be called. A closure that
moves captured values out of its body will only implement `FnOnce` and none
of the other `Fn` traits, because it can only be called once.
at least this trait because all closures can be called. A closure that moves
captured values out of its body will only implement `FnOnce` and none of the
other `Fn` traits, because it can only be called once.
2. `FnMut` applies to closures that don’t move captured values out of their
body, but that might mutate the captured values. These closures can be
called more than once.
Expand Down Expand Up @@ -380,7 +380,7 @@ compiler won’t let us use this closure with `sort_by_key`:
This is a contrived, convoluted way (that doesn’t work) to try and count the
number of times `sort_by_key` calls the closure when sorting `list`. This code
attempts to do this counting by pushing `value`—a `String` from the closure’s
environment—into the `sort_operations` vector. The closure captures `value`
environment—into the `sort_operations` vector. The closure captures `value` and
then moves `value` out of the closure by transferring ownership of `value` to
the `sort_operations` vector. This closure can be called once; trying to call
it a second time wouldn’t work because `value` would no longer be in the
Expand All @@ -395,12 +395,11 @@ implement `FnMut`:

The error points to the line in the closure body that moves `value` out of the
environment. To fix this, we need to change the closure body so that it doesn’t
move values out of the environment. To count the number of times the closure
is called, keeping a counter in the environment and incrementing its value in
the closure body is a more straightforward way to calculate that. The closure
in Listing 13-9 works with `sort_by_key` because it is only capturing a mutable
reference to the `num_sort_operations` counter and can therefore be called more
than once:
move values out of the environment. Keeping a counter in the environment and
incrementing its value in the closure body is a more straightforward way to
count the number of times the closure is called. The closure in Listing 13-9
works with `sort_by_key` because it is only capturing a mutable reference to the
`num_sort_operations` counter and can therefore be called more than once:

<Listing number="13-9" file-name="src/main.rs" caption="Using an `FnMut` closure with `sort_by_key` is allowed">

Expand Down
18 changes: 9 additions & 9 deletions src/ch13-02-iterators.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ you would likely write this same functionality by starting a variable at index
incrementing the variable value in a loop until it reached the total number of
items in the vector.

Iterators handle all that logic for you, cutting down on repetitive code you
Iterators handle all of that logic for you, cutting down on repetitive code you
could potentially mess up. Iterators give you more flexibility to use the same
logic with many different kinds of sequences, not just data structures you can
index into, like vectors. Let’s examine how iterators do that.
Expand All @@ -64,7 +64,7 @@ pub trait Iterator {
}
```

Notice this definition uses some new syntax: `type Item` and `Self::Item`,
Notice that this definition uses some new syntax: `type Item` and `Self::Item`,
which are defining an _associated type_ with this trait. We’ll talk about
associated types in depth in Chapter 20. For now, all you need to know is that
this code says implementing the `Iterator` trait requires that you also define
Expand All @@ -73,7 +73,7 @@ method. In other words, the `Item` type will be the type returned from the
iterator.

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
`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-12 demonstrates
Expand Down Expand Up @@ -102,7 +102,7 @@ ownership of `v1` and returns owned values, we can call `into_iter` instead of
`iter`. Similarly, if we want to iterate over mutable references, we can call
`iter_mut` instead of `iter`.

### Methods that Consume the Iterator
### Methods That Consume the Iterator

The `Iterator` trait has a number of different methods with default
implementations provided by the standard library; you can find out about these
Expand All @@ -111,12 +111,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
`Iterator` trait.

Methods that call `next` are called _consuming adapters_, because calling them
Methods that call `next` are called _consuming adapters_ 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-13 has a
test illustrating a use of the `sum` method:
test illustrating a use of the `sum` method.

<Listing number="13-13" file-name="src/lib.rs" caption="Calling the `sum` method to get the total of all items in the iterator">

Expand Down Expand Up @@ -161,12 +161,12 @@ we need to consume the iterator here.

To fix this warning and consume the iterator, we’ll use the `collect` method,
which we used in Chapter 12 with `env::args` in Listing 12-1. This method
consumes the iterator and collects the resulting values into a collection data
consumes the iterator and collects the resultant values into a collection data
type.

In Listing 13-15, we collect the results of iterating over the iterator that’s
returned from the call to `map` into a vector. This vector will end up
containing each item from the original vector incremented by 1.
containing each item from the original vector, incremented by 1.

<Listing number="13-15" file-name="src/main.rs" caption="Calling the `map` method to create a new iterator and then calling the `collect` method to consume the new iterator and create a vector">

Expand All @@ -185,7 +185,7 @@ 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
consuming adapter methods to get results from calls to iterator adapters.

### Using Closures that Capture Their Environment
### Using Closures That Capture Their Environment

Many iterator adapters take closures as arguments, and commonly the closures
we’ll specify as arguments to iterator adapters will be closures that capture
Expand Down
19 changes: 9 additions & 10 deletions src/ch13-03-improving-our-io-project.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ In 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-17,
we’ve reproduced the implementation of the `Config::build` function as it was
in Listing 12-23:
in Listing 12-23.

<Listing number="13-17" file-name="src/lib.rs" caption="Reproduction of the `Config::build` function from Listing 12-23">

Expand Down Expand Up @@ -98,7 +98,7 @@ iterating over it, we can add the `mut` keyword into the specification of the

Next, we’ll fix the body of `Config::build`. Because `args` implements the
`Iterator` trait, we know we can call the `next` method on it! Listing 13-20
updates the code from Listing 12-23 to use the `next` method:
updates the code from Listing 12-23 to use the `next` method.

<Listing number="13-20" file-name="src/lib.rs" caption="Changing the body of `Config::build` to use iterator methods">

Expand All @@ -110,11 +110,11 @@ updates the code from Listing 12-23 to use the `next` method:

Remember that the first value in the return value of `env::args` is the name of
the program. We want to ignore that and get to the next value, so first we call
`next` and do nothing with the return value. Second, we call `next` to get the
value we want to put in the `query` field of `Config`. If `next` returns a
`Some`, we use a `match` to extract the value. If it returns `None`, it means
not enough arguments were given and we return early with an `Err` value. We do
the same thing for the `file_path` value.
`next` and do nothing with the return value. Then we call `next` to get the
value we want to put in the `query` field of `Config`. If `next` returns `Some`,
we use a `match` to extract the value. If it returns `None`, it means not enough
arguments were given and we return early with an `Err` value. We do the same
thing for the `file_path` value.

### Making Code Clearer with Iterator Adapters

Expand Down Expand Up @@ -146,7 +146,7 @@ concurrent access to the `results` vector. Listing 13-22 shows this change:

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-16, this code uses the `filter` adapter to keep only the lines that
13-16, this code uses the `filter` adapter to keep only the lines for which
`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
Expand All @@ -166,7 +166,6 @@ that are unique to this code, such as the filtering condition each element in
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. Let’s talk about
performance.
might be that the lower-level loop will be faster. Let’s talk about performance.

[impl-trait]: ch10-02-traits.html#traits-as-parameters
4 changes: 2 additions & 2 deletions src/ch13-04-performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ various sizes as the `contents`, different words and words of different lengths
as the `query`, and all kinds of other variations. The point is this:
iterators, although a high-level abstraction, get compiled down to roughly the
same code as if you’d written the lower-level code yourself. Iterators are one
of Rust’s _zero-cost abstractions_, by which we mean using the abstraction
of Rust’s _zero-cost abstractions_, by which we mean that using the abstraction
imposes no additional runtime overhead. This is analogous to how Bjarne
Stroustrup, the original designer and implementor of C++, defines
_zero-overhead_ in “Foundations of C++” (2012):
Expand Down Expand Up @@ -76,7 +76,7 @@ the loop.

All of the coefficients get stored in registers, which means accessing the
values is very fast. There are no bounds checks on the array access at runtime.
All these optimizations that Rust is able to apply make the resulting code
All these optimizations that Rust is able to apply make the resultant code
extremely efficient. Now that you know this, you can use iterators and closures
without fear! They make code seem like it’s higher level but don’t impose a
runtime performance penalty for doing so.
Expand Down
2 changes: 1 addition & 1 deletion src/ch14-01-release-profiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ opt-level = 3
The `opt-level` setting controls the number of optimizations Rust will apply to
your code, with a range of 0 to 3. Applying more optimizations extends
compiling time, so if you’re in development and compiling your code often,
you’ll want fewer optimizations to compile faster even if the resulting code
you’ll want fewer optimizations to compile faster even if the resultant code
runs slower. The default `opt-level` for `dev` is therefore `0`. When you’re
ready to release your code, it’s best to spend more time compiling. You’ll only
compile in release mode once, but you’ll run the compiled program many times,
Expand Down
Loading

0 comments on commit 349e17c

Please sign in to comment.