Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Edits from copyediting #1791

Merged
merged 7 commits into from
Jan 30, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Changes extracted to nostarch snapshot for review
  • Loading branch information
carols10cents committed Jan 30, 2019
commit 46cb655ccc3831cad9861871eaad6c1455522068
38 changes: 20 additions & 18 deletions nostarch/chapter03-integer-overflow-box.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
Please place this text in a box after the "Integer Types" section ends and before the "Floating-Point Types" section begins on page 38.
Please place this text in a box after the "Integer Types" section ends and
before the "Floating-Point Types" section begins on page 38.

##### Integer Overflow
### Integer Overflow

Let’s say that you have a variable of type `u8`, which can hold values
between 0 and 255. What happens if you try to change the variable's value to
256? This is called *integer overflow*, and Rust has some interesting rules
around this behavior. When compiling in debug mode, Rust includes checks for
integer overflow that will cause your program to *panic* at runtime if integer
overflow occurs. Panicking is the term Rust uses when a program exits with an
error; we’ll discuss panics more in the "Unrecoverable Errors with `panic!`
section" of Chapter 9 on page XX.
Let’s say you have a variable of type `u8` that can hold values between 0 and
255. If you try to change the variable to a value outside of that range, such
as 256, *integer overflow* will occur. Rust has some interesting rules
involving this behavior. When you’re compiling in debug mode, Rust includes
checks for integer overflow that causes your program to *panic* at runtime if
this behavior occurs. Rust uses the term panicking when a program exits with an
error; we’ll discuss panics in more depth in the section “Unrecoverable Errors
with `panic!`” in Chapter 9 on page XX.

When compiling in release mode with the `--release` flag, Rust does not
include checks for integer overflow that cause panics. Instead, if overflow
occurs, Rust will perform something called *two’s complement wrapping*. In
short, values greater than the maximum value the type can hold "wrap around"
to the minimum of the values the type can hold. In the case of a `u8`, 256
becomes 0, 257 becomes 1, etc. Relying on the wrapping behavior of integer
overflow is considered an error. If you want to wrap explicitly, the standard
library has a type named `Wrapping` that provides this behavior.
When you’re compiling in release mode with the `--release` flag, Rust does
*not* include checks for integer overflow that cause panics. Instead, if
overflow occurs, Rust performs *two’s complement wrapping*. In short, values
greater than the maximum value the type can hold “wrap around” to the minimum
of the values the type can hold. In the case of a `u8`, 256 becomes 0, 257
becomes 1, and so on. The program won’t panic, but the variable will have a
value that probably isn’t what you were expecting it to have. Relying on
integer overflow’s wrapping behavior is considered an error. If you want to
wrap explicitly, you can use the standard library type `Wrapping`.
17 changes: 9 additions & 8 deletions nostarch/chapter03-new-array-text.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
Please add this text at the end of The Array Type section, just before the Accessing Array Elements subsection starts on page 41.
Please add this text at the end of The Array Type section, just before the
Accessing Array Elements subsection starts on page 41.

Writing an array's type is done with square brackets containing the type of
each element in the array followed by a semicolon and the number of elements in
the array, like so:
You would write an arrays type by using square brackets, and within the
brackets include the type of each element, a semicolon, and then the number of
elements in the array, like so:

```rust
let a: [i32; 5] = [1, 2, 3, 4, 5];
Expand All @@ -11,15 +12,15 @@ let a: [i32; 5] = [1, 2, 3, 4, 5];
Here, `i32` is the type of each element. After the semicolon, the number `5`
indicates the element contains five items.

The way an array's type is written looks similar to an alternative syntax for
Writing an arrays type this way looks similar to an alternative syntax for
initializing an array: if you want to create an array that contains the same
value for each element, you can specify the initial value, then a semicolon,
then the length of the array in square brackets as shown here:
value for each element, you can specify the initial value, followed by a
semicolon, and then the length of the array in square brackets, as shown here:

```rust
let a = [3; 5];
```

The array named `a` will contain 5 elements that will all be set to the value
The array named `a` will contain `5` elements that will all be set to the value
`3` initially. This is the same as writing `let a = [3, 3, 3, 3, 3];` but in a
more concise way.
28 changes: 15 additions & 13 deletions nostarch/chapter03-returning-values-from-loops.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
Please insert this new section after the "Repeating Code with loop" section ends and before the "Conditional Loops with while" section starts, on page 53.
Please insert this new section after the “Repeating Code with loop” section
ends and before the “Conditional Loops with while” section starts, on page 53.

#### Returning Values From Loops
#### Returning Values from Loops

One of the uses of a `loop` is to retry an operation you know can fail, such as
checking if a thread completed its job. However, you might need to pass the
result of that operation to the rest of your code. If you add the value you
want to return after the `break` expression you use to stop the loop, it will
be returned out of the loop so you can use the value, as shown here:
One of the uses of a `loop` is to retry an operation you know might fail, such
as checking whether a thread has completed its job. However, you might need to
pass the result of that operation to the rest of your code. To do this, you can
add the value you want returned after the `break` expression you use to stop
the loop; that value will be returned out of the loop so you can use it, as
shown here:

```rust
fn main() {
Expand All @@ -25,9 +27,9 @@ fn main() {
```

Before the loop, we declare a variable named `counter` and initialize it to
zero. Then we declare a variable named `result` to hold the value returned from
the loop. On every iteration of the loop, we add one to the counter variable,
and then check if the counter is equal to ten. When it is, we use the `break`
keyword with the value `counter * 2`. After the loop, we place a semicolon to
end the statement assigning the value to `result`. Finally, we print out the
value in `result`, which in this case will be twenty.
`0`. Then we declare a variable named `result` to hold the value returned from
the loop. On every iteration of the loop, we add `1` to the `counter` variable,
and then check whether the counter is equal to `10`. When it is, we use the
`break` keyword with the value `counter * 2`. After the loop, we use a
semicolon to end the statement that assigns the value to `result`. Finally, we
print the value in `result`, which in this case is 20.
13 changes: 8 additions & 5 deletions nostarch/chapter04-error-message-updates.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
Please view this file in monospace to see how the error messages should line up vertically.
Please view this file in monospace to see how the error messages should line up
vertically.

Here is the new error message for page 70, I've included the whole message for clarity:
Here is the new error message for page 70, I’ve included the whole message for
clarity:

```
error[E0499]: cannot borrow `s` as mutable more than once at a time
Expand All @@ -18,7 +20,8 @@ error[E0499]: cannot borrow `s` as mutable more than once at a time
For page 71:

```
error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable
error[E0502]: cannot borrow `s` as mutable because it is also borrowed as
immutable
--> src/main.rs:6:14
|
4 | let r1 = &s; // no problem
Expand All @@ -34,7 +37,8 @@ error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immuta
For page 77:

```
error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable
error[E0502]: cannot borrow `s` as mutable because it is also borrowed as
immutable
--> src/main.rs:18:5
|
16 | let word = first_word(&s);
Expand All @@ -46,4 +50,3 @@ error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immuta
20 | println!("the first word is: {}", word);
| ---- immutable borrow later used here
```

38 changes: 21 additions & 17 deletions nostarch/chapter04-stack-heap-box-edits.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
Please replace the paragraphs that start with "The stack is fast" and "Data with a size unknown" in the box on page 58 with this paragraph:
Please replace the paragraphs that start with “The stack is fast” and “Data
with a size unknown” in the box on page 58 with this paragraph:

---

All data stored on the stack must have a known, fixed size. Data with a size
that is unknown at compile time or a size that might change must be stored on
the heap instead. The heap is less organized: when you put data on the heap,
you ask for some amount of space. The operating system finds an empty spot
somewhere in the heap that is big enough, marks it as being in use, and
returns a *pointer*, which is the address of that location. This process is
called *allocating on the heap*, sometimes abbreviated as just allocating.”
Pushing values onto the stack is not considered allocating. Because the
pointer is a known, fixed size, you can store the pointer on the stack, but
when you want the actual data, you have to follow the pointer.
All data stored on the stack must have a known, fixed size. Data with an
unknown size at compile time or a size that might change must be stored on the
heap instead. The heap is less organized: when you put data on the heap, you
request a certain amount of space. The operating system finds an empty spot in
the heap that is big enough, marks it as being in use, and returns a *pointer*,
which is the address of that location. This process is called *allocating on
the heap* and is sometimes abbreviated as just *allocating*. Pushing values
onto the stack is not considered allocating. Because the pointer is a known,
fixed size, you can store the pointer on the stack, but when you want the
actual data, you must follow the pointer.

---

Then please add this paragraph between the paragraph that starts with "Think of being seated at a restaurant" and the paragraph that starts with "Accessing data in the heap" on page 59:
Then please add this paragraph between the paragraph that starts with “Think of
being seated at a restaurant” and the paragraph that starts with “Accessing
data in the heap” on page 59:

---

Pushing to the stack is faster than allocating on the heap because it never
has to search for a place to put new data; that place is always at the top
of the stack. Comparatively, allocating space on the heap requires more work,
because the operating system must first find a space big enough to hold the
data and then perform bookkeeping to prepare for the next allocation.
Pushing to the stack is faster than allocating on the heap because the
operating system never has to search for a place to store new data; that
location is always at the top of the stack. Comparatively, allocating space on
the heap requires more work, because the operating system must first find a big
enough space to hold the data and then perform bookkeeping to prepare for the
next allocation.

---
26 changes: 15 additions & 11 deletions nostarch/chapter09-error-message-updates.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ error[E0277]: the `?` operator can only be used in a function that returns
Then, please replace the highlighted paragraph on page 161 with this text:

This error points out that we’re only allowed to use the `?` operator in a
function that returns `Result<T, E>`. In functions that don’t return `Result<T,
E>`, when you call other functions that return `Result<T, E>`, you’ll need to
use a `match` or one of the `Result<T, E>` methods to handle the `Result<T, E>`
instead of using the `?` operator to potentially propagate the error to the
calling code.

However, we can change how we write the `main` function so that it does return
a `Result<T, E>`:
function that returns `Result<T, E>`. When you’re writing code in a function
that doesn’t return `Result<T, E>`, and you want to use `?` when you call other
functions that return `Result<T, E>`, you have two choices to fix this problem.
One technique is to change the return type of your function to be `Result<T,
E>` if you have no restrictions preventing that. The other technique is to use
a `match` or one of the `Result<T, E>` methods to handle the `Result<T, E>` in
whatever way is appropriate.

The `main` function is special, and there are restrictions on what its return
type must be. One valid return type for main is `()`, and conveniently, another
valid return type is `Result<T, E>`, as shown here:

```
use std::error::Error;
Expand All @@ -38,6 +41,7 @@ fn main() -> Result<(), Box<dyn Error>> {
}
```

The `Box<dyn Error>` type is called a “trait object,” which we’ll talk about in
the “Using Trait Objects that Allow for Values of Different Types” section of
Chapter 17. For now, you can read `Box<dyn Error>` to mean “any kind of error.”
The `Box<dyn Error>` type is called a *trait object*, which we’ll talk
about in the section “Using Trait Objects that Allow for Values of Different
Types” in Chapter 17. For now, you can read `Box<dyn Error>` to mean “any
kind of error.” Using `?` in a `main` function with this return type is allowed.
30 changes: 16 additions & 14 deletions nostarch/chapter09-match-update.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
Please enter this text to replace the highlighted text that starts with "However," at the bottom of page 156 and top of page 157.
Please enter this text to replace the highlighted text that starts with
“However,” at the bottom of page 156 and top of page 157.

---

However, because `File::create` could also fail, we need a second arm in the
inner `match` expression. When the file can’t be created, a different error
message will be printed. The second arm of the outer `match` stays the same so
the program panics on any error besides the missing file error.
message is printed. The second arm of the outer `match` stays the same, so the
program panics on any error besides the missing file error.

That’s a lot of `match`! The `match` expression is very useful, but also very
much a primitive. In Chapter 13, we’ll learn about closures. The `Result<T, E>`
type has many methods that accept a closure and are implemented using `match`
expressions, and using those methods will make your code more concise. A more
seasoned Rustacean might write this code instead of Listing 9-5:
That’s a lot of `match`! The `match` expression is very useful but also very
much a primitive. In Chapter 13, you’ll learn about closures; the `Result<T,
E>` type has many methods that accept a closure and are implemented using
`match` expressions. Using those methods will make your code more concise. A
more seasoned Rustacean might write this code instead of Listing 9-5:

```
use std::fs::File;
Expand All @@ -21,7 +22,8 @@ fn main() {
let f = File::open("hello.txt").unwrap_or_else(|error| {
if error.kind() == ErrorKind::NotFound {
File::create("hello.txt").unwrap_or_else(|error| {
panic!("Tried to create file but there was a problem: {:?}", error);
panic!("Tried to create file but there was a problem: {:?}",
error);
})
} else {
panic!("There was a problem opening the file: {:?}", error);
Expand All @@ -30,8 +32,8 @@ fn main() {
}
```

This code has the same behavior as that of Listing 9-5 but doesn't contain any
`match` expressions and is a bit cleaner to read. Come back to this example
after you’ve read Chapter 13, and look up the `unwrap_or_else` method in the
standard library documentation. There’s many more of these methods that can
clean up huge nested `match` expressions when dealing with errors.
Although this code has the same behavior as Listing 9-5, it doesnt contain any
`match` expressions and is cleaner to read. Come back to this example after
you’ve read Chapter 13, and look up the `unwrap_or_else` method in the standard
library documentation. Many more of these methods can clean up huge nested
`match` expressions when you’re dealing with errors.
21 changes: 12 additions & 9 deletions nostarch/chapter09-read-to-string-update.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
Please insert this text after the paragraph ending in "ergonomic way to write it" on page 160.
Please insert this text after the paragraph ending in “ergonomic way to write
it” on page 160.

---

Speaking of different ways to write this function, there’s a way to make this
even shorter, shown in Listing 9-9.
Speaking of different ways to write this function, Listing 9-9 shows that
there’s a way to make this even shorter.

Filename: src/main.rs

Expand All @@ -16,10 +17,12 @@ fn read_username_from_file() -> Result<String, io::Error> {
}
```

Listing 9-9: Using `fs::read_to_string` instead of opening then reading the file
Listing 9-9: Using `fs::read_to_string` instead of opening and then reading the
file

Reading a file into a string is a fairly common operation, so Rust provides a
convenience function called `fs::read_to_string` that will open the file,
create a new `String`, read the contents of the file, put the contents into
that `String`, and return it. Of course, this doesn’t give us the opportunity
to explain all the error handling, so we did it the longer way first.
Reading a file into a string is a fairly common operation, so Rust provides the
convenient `fs::read_to_string` function that opens the file, creates a new
`String`, reads the contents of the file, puts the contents into that `String`,
and returns it. Of course, using `fs::read_to_string` doesn’t give us the
opportunity to explain all the error handling, so we did it the longer way
first.
Loading