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
Propagate changes from nostarch to src
  • Loading branch information
carols10cents committed Jan 30, 2019
commit 50b54b71486c32e9eb9d4d9a9395852af833bca8
48 changes: 25 additions & 23 deletions src/ch03-02-data-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,23 +100,24 @@ which you’d use `isize` or `usize` is when indexing some sort of collection.

> ##### 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"][unrecoverable-errors-with-panic] of Chapter 9.
> 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 [Unrecoverable Errors
> with `panic!`”][unrecoverable-errors-with-panic] section in Chapter 9.
>
> 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`][wrapping].

#### Floating-Point Types

Expand Down Expand Up @@ -323,9 +324,9 @@ let months = ["January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"];
```

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 @@ -334,16 +335,16 @@ 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.

Expand Down Expand Up @@ -415,3 +416,4 @@ ch02-00-guessing-game-tutorial.html#comparing-the-guess-to-the-secret-number
[control-flow]: ch03-05-control-flow.html#control-flow
[strings]: ch08-02-strings.html#storing-utf-8-encoded-text-with-strings
[unrecoverable-errors-with-panic]: ch09-01-unrecoverable-errors-with-panic.html
[wrapping]: ../std/num/struct.Wrapping.html
25 changes: 13 additions & 12 deletions src/ch03-05-control-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,13 +309,14 @@ stop executing the loop. Recall that we did this in the guessing game in the
--> section of Chapter 2 to exit the program when the user won the game by
guessing the correct number.

#### 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 @@ -334,12 +335,12 @@ 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.

#### Conditional Loops with `while`

Expand Down
25 changes: 13 additions & 12 deletions src/ch04-01-what-is-ownership.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,27 +39,28 @@ strings.
> bottom wouldn’t work as well! Adding data is called *pushing onto the stack*,
> and removing data is called *popping off the stack*.
>
> 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
> 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 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.”
> 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 have to follow the pointer.
> when you want the actual data, you must follow the pointer.
>
> Think of being seated at a restaurant. When you enter, you state the number of
> people in your group, and the staff finds an empty table that fits everyone
> and leads you there. If someone in your group comes late, they can ask where
> you’ve been seated to find you.
>
> 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.
>
> Accessing data in the heap is slower than accessing data on the stack because
> you have to follow a pointer to get there. Contemporary processors are faster
Expand Down
72 changes: 40 additions & 32 deletions src/ch09-02-recoverable-errors-with-result.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,15 +184,15 @@ The condition we want to check in the inner match is whether the value returned
by `error.kind()` is the `NotFound` variant of the `ErrorKind` enum. If it is,
we try to create the file with `File::create`. 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.
file can’t be created, a different 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:

```rust,ignore
use std::fs::File;
Expand All @@ -211,11 +211,11 @@ 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.

### Shortcuts for Panic on Error: `unwrap` and `expect`

Expand Down Expand Up @@ -446,8 +446,8 @@ 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.

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.

<span class="filename">Filename: src/main.rs</span>

Expand All @@ -461,13 +461,14 @@ fn read_username_from_file() -> Result<String, io::Error> {
```

<span class="caption">Listing 9-9: Using `fs::read_to_string` instead of
opening then reading the file</span>
opening and then reading the file</span>

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.

#### The `?` Operator Can Only Be Used in Functions That Return `Result`

Expand Down Expand Up @@ -504,14 +505,17 @@ error[E0277]: the `?` operator can only be used in a function that returns
```

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:

```rust,ignore
use std::error::Error;
Expand All @@ -524,10 +528,14 @@ 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 [“Using Trait Objects that Allow for Values of Different
Types”][trait-objects]<!-- ignore --> section 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.

Now that we’ve discussed the details of calling `panic!` or returning `Result`,
let’s return to the topic of how to decide which is appropriate to use in which
cases.

[trait-objects]: ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types
Loading