Propagate changes

This commit is contained in:
Carol (Nichols || Goulding) 2019-02-15 13:09:26 -05:00
parent 3c9cb68236
commit ce8d942907
No known key found for this signature in database
GPG Key ID: D04B39A6CA243902
11 changed files with 659 additions and 846 deletions

File diff suppressed because it is too large Load Diff

View File

@ -5,10 +5,9 @@ Please insert this text on page 215 between the last two paragraphs before the
### Using `Result<T, E>` in Tests
So far, weve written tests that fail when code within the test panics. We can
also write tests that use `Result<T, E>` and fail when code within the test
returns the `Err` variant! Heres the test from Listing 11-1, rewritten to use
`Result<T, E>` instead of panicking:
So far, weve written tests that panic when they fail. We can also write tests
that use `Result<T, E>`! Heres the test from Listing 11-1, rewritten to use
`Result<T, E>` and return an `Err` instead of panicking:
```rust
#[cfg(test)]
@ -27,9 +26,11 @@ mod tests {
The `it_works` function now has a return type, `Result<(), String>`. In the
body of the function, rather than calling the `assert_eq!` macro, we return
`Ok(())` when the test passes and an `Err` with a `String` inside when the test
fails. Writing tests that return a `Result<T, E>` enables you to use the `?`
operator in the body of tests, which can be a convenient way to write tests
that should fail if any operation within them returns an `Err` variant.
fails.
Writing tests so they return a `Result<T, E>` enables you to use the question
mark operator in the body of tests, which can be a convenient way to write
tests that should fail if any operation within them returns an `Err` variant.
You cant use the `#[should_panic]` annotation on tests that use `Result<T,
E>`. Instead, you should return an `Err` value directly when the test should

View File

@ -1,10 +1,10 @@
#### Destructuring Nested Structs and Enums
Up until now, all of our examples have been matching structs or enums that were
one level deep. Matching can work on nested items too!
Until now, all our examples have been matching structs or enums that were one
level deep. Matching can work on nested items too!
For example, we can refactor the code in Listing 18-15 to support both RGB and
HSV colors in the `ChangeColor` message, as shown in Listing 18-16.
For example, we can refactor the code in Listing 18-15 to support RGB and HSV
colors in the `ChangeColor` message, as shown in Listing 18-16.
```rust
enum Color {
@ -47,8 +47,8 @@ fn main() {
<span class="caption">Listing 18-16: Matching on nested enums</span>
The pattern of the first arm in the `match` expression matches a
`Message::ChangeColor` enum variant that contains a `Color::Rgb` variant, and
then the pattern binds to the three inner `i32` values. The pattern of the
second arm also matches a `Message::ChangeColor` enum variant, but the inner
enum matches the `Color::Hsv` variant instead. We can specify these complex
conditions in one `match` expression even though two enums are involved.
`Message::ChangeColor` enum variant that contains a `Color::Rgb` variant; then
the pattern binds to the three inner `i32` values. The pattern of the second
arm also matches a `Message::ChangeColor` enum variant, but the inner enum
matches the `Color::Hsv` variant instead. We can specify these complex
conditions in one `match` expression, even though two enums are involved.

View File

@ -1,57 +1,50 @@
# Managing Growing Projects with Packages, Crates, and Modules
As you write larger programs, organizing your code is important because itll
become impossible to keep track of your entire program in your head at one
time. By grouping related functionality together and separating code with
distinct features apart, youll make it clear where to find code that
implements a particular feature and youll know where to go to change how a
feature works.
As you write large programs, organizing your code is important because itll
become impossible to keep track of your entire program in your head. By
grouping related functionality and separating code with distinct features,
youll clarify where to find code that implements a particular feature and
where to go to change how a feature works.
The programs weve written so far have been written in one module in one file.
As a project grows, you can organize code by splitting into multiple modules,
The programs weve written so far have been in one module in one file. As a
project grows, you can organize code by splitting it into multiple modules and
then multiple files. A package can contain multiple binary crates and
optionally one library crate. As a package grows, you can extract parts into
separate crates that become external dependencies. Well be covering all these
techniques in this chapter. For really large projects of a set of interrelated
packages that evolve together, Cargo provides the concept of *workspaces* that
well cover in the [“Cargo Workspaces”][workspaces]<!-- ignore --> section of
Chapter 14.
separate crates that become external dependencies. This chapter covers all
these techniques. For very large projects of a set of interrelated packages
that evolve together, Cargo provides *workspaces*, which well cover in the
section [“Cargo Workspaces”][workspaces]<!-- ignore --> in Chapter 14.
In addition to grouping functionality, encapsulating implementation details
lets you reuse code at a higher level: once youve implemented an operation,
other code can call that code without knowing exactly how the implementation
works via the codes public interface. The way you choose to write the code
defines what parts are public for other code to use and what parts are private
implementation details that you reserve the right to change and that other code
shouldnt have to worry about. This is another way to limit the amount of
detail you have to keep in your head.
other code can call that code via the codes public interface without knowing
how the implementation works. The way you write code defines which parts are
public for other code to use and which parts are private implementation details
that you reserve the right to change. This is another way to limit the amount
of detail you have to keep in your head.
A related aspect to organization and encapsulation is *scope*: the nested
context code is written in that has a set of names that are defined as “in
context in which code is written has a set of names that are defined as “in
scope.” When reading, writing, and compiling code, programmers and compilers
need to know whether a particular name at a particular spot refers to a
variable, function, struct, enum, module, constant, or other item, and what
that item means. We can create scopes and change what names are in or out of
scope. Were not allowed to have two items with the same name in the same
scope; there are tools to resolve name conflicts.
that item means. You can create scopes and change which names are in or out of
scope. You cant have two items with the same name in the same scope; tools are
available to resolve name conflicts.
Rust has a number of features that allow you to manage the organization of your
code, which details are exposed and which details are private, and what names
are in each scope in your programs. These features are sometimes collectively
referred to as “the module system.” They are:
Rust has a number of features that allow you to manage your codes
organization, including which details are exposed and which details are
private, and what names are in each scope in your programs. These features are
sometimes collectively referred to as the *module system* and include:
<!-- Liz: these bullet points were in order from most general to least general,
so I've put them back in that order. Was there a reason you reordered them?
/Carol -->
* **Packages:** A Cargo feature that lets you build, test, and share crates
* **Crates:** A tree of modules that produces a library or executable
* **Modules** and **use:** Let you control the organization, scope, and
privacy of paths
* **Paths:** A way of naming an item, such as a struct, function, or module
* *Packages*, a Cargo feature that lets you build, test, and share crates.
* *Crates*, a tree of modules that produces a library or executable.
* *Modules* and *use*, which let you control the organization, scope, and
privacy of paths.
* *Paths*, a way of naming an item such as a struct, function, or module.
In this chapter well cover all of these features and discuss how they interact
and how theyre used to manage scope. By the end, you should have a solid
understanding of the module system, and be able to work with scopes like a pro!
In this chapter, well cover all these features, discuss how they interact, and
explain how to use them to manage scope. By the end, you should have a solid
understanding of the module system and be able to work with scopes like a pro!
[workspaces]: ch14-03-cargo-workspaces.html

View File

@ -1,37 +1,20 @@
## Packages and Crates
The first parts of the module system well cover are *packages* and *crates*.
The first parts of the module system well cover are *packages* and *crates*. A
*crate* is a binary or library. The *crate root* is a source file that the Rust
compiler starts from and makes up the root module of your crate (well explain
modules in depth in the section ["Defining Modules to Control Scope and
Privacy"][modules]<!-- ignore -->). A *package* is one or more crates that
provide a set of functionality. A package contains a *Cargo.toml* file that
describes how to build those crates.
A *crate* is a binary or library.
<!--- Below: who is using the source file to build the crate? Can you specify
in text? --->
<!-- Done /Carol -->
The *crate root* is a source file that the Rust compiler starts from, and makes
up the root module of your crate (we'll be explaining modules in depth in the
["Defining Modules to Control Scope and Privacy"][modules]<!-- ignore -->
section). A *package* is one or more crates that, together, provide a set of
functionality. A package contains a *Cargo.toml* that describes how to build
those crates.
<!--- Above: can you say what a package is? don't think this is technically
correct but something structured like "A package is a group of files that
describe how to build one or more crate. They include a Cargo.toml file. ": or
something like that. --->
<!-- Done /Carol -->
There are several rules about what a package can contain. A package *must*
contain zero or one library crates, and no more. It can contain as many binary
crates as youd like, but it must contain at least one crate (either library or
Several rules determine what a package can contain. A package *must* contain
zero or one library crates, and no more. It can contain as many binary crates
as youd like, but it must contain at least one crate (either library or
binary).
<!--- are they already familiar with the distinction between these two
types of crate? --->
<!-- Yes, we covered this in chapter 2. /Carol -->
Now lets walk through what happens when you create a package. First, we enter
the command `cargo new`:
Lets walk through what happens when we create a package. First, we enter the
command `cargo new`:
```text
$ cargo new my-project
@ -43,48 +26,37 @@ $ ls my-project/src
main.rs
```
<!-- Should there be mention of src.main? -->
<!-- No, I've clarified /Carol -->
When we entered the command, Cargo created a *Cargo.toml*, giving us a package.
If we look at the contents of *Cargo.toml*, theres no mention of *src/main.rs*
because Cargo follows a convention that *src/main.rs* is the crate root of a
binary crate with the same name as the package. Likewise, Cargo knows that if
the package directory contains *src/lib.rs*, then the package contains a
library crate with the same name as the package, and *src/lib.rs* is its crate
root. Cargo passes the crate root files to `rustc` to actually build the
library or binary.
<!--- below: can you introduce these hypotheticals by describing what's in the
package above so the reader has a concrete example? --->
<!-- Done /Carol -->
When we entered the command, Cargo created a *Cargo.toml* file, giving us a
package. Looking at the contents of *Cargo.toml*, theres no mention of
*src/main.rs* because Cargo follows a convention that *src/main.rs* is the
crate root of a binary crate with the same name as the package. Likewise, Cargo
knows that if the package directory contains *src/lib.rs*, the package contains
a library crate with the same name as the package, and *src/lib.rs* is its
crate root. Cargo passes the crate root files to `rustc` to build the library
or binary.
Here, we have a package that only contains *src/main.rs*, meaning it only
contains a binary crate named `my-project`. If a package contains both
*src/main.rs* and *src/lib.rs*, then it has two crates: a library and a binary,
both with the same name as the package. A package can have multiple binary
crates by placing files in the *src/bin* directory: each file will be a
separate binary crate.
contains a binary crate named `my-project`. If a package contains *src/main.rs*
and *src/lib.rs*, it has two crates: a library and a binary, both with the same
name as the package. A package can have multiple binary crates by placing files
in the *src/bin* directory: each file will be a separate binary crate.
A crate groups related functionality together in a scope so that the
A crate will group related functionality together in a scope so the
functionality is easy to share between multiple projects. For example, the
`rand` crate that we used in Chapter 2 provides functionality having to do with
generating random numbers. We can use that functionality in our own projects by
bringing the `rand` crate into our projects scope. All of the functionality
provided by the `rand` crate is accessible through the crates name, `rand`.
`rand` crate we used in Chapter 2 provides functionality that generates random
numbers. We can use that functionality in our own projects by bringing the
`rand` crate into our projects scope. All the functionality provided by the
`rand` crate is accessible through the crates name, `rand`.
In addition to making it clear whether functionality is defined in our crate or
the `rand` crate, keeping a crates functionality in its own scope prevents
conflicts that could arise. For example, the `rand` crate provides a trait
named `Rng`. We can also define a `struct` named `Rng` in our own crate.
Because a crates functionality is namespaced in its own scope, when we add
`rand` as a dependency, the compiler isnt confused about what the name `Rng`
refers to. In our crate, it refers to the `struct Rng` that we defined. The
`Rng` trait from the `rand` crate is accessible as `rand::Rng`.
Keeping a crates functionality in its own scope clarifies whether particular
functionality is defined in our crate or the `rand` crate and prevents
potential conflicts. For example, the `rand` crate provides a trait named
`Rng`. We can also define a `struct` named `Rng` in our own crate. Because a
crates functionality is namespaced in its own scope, when we add `rand` as a
dependency, the compiler isnt confused about what the name `Rng` refers to. In
our crate, it refers to the `struct Rng` that we defined. We would access the
`Rng` trait from the `rand` crate as `rand::Rng`.
<!--- how do crates relate to scope? Could you address in text --->
<!-- Done, above /Carol -->
Now that weve covered crates, lets talk about the module system!
Lets move on and talk about the module system!
[modules]: ch07-02-defining-modules-to-control-scope-and-privacy.html

View File

@ -1,31 +1,30 @@
## Defining Modules to Control Scope and Privacy
In this section, well talk about modules and the other aspects that are
considered part of the module system, namely *paths* that allow you to name
items; the `use` keyword that brings a path into scope; and the `pub` keyword
to make items public. Well also cover using the `as` keyword, external
packages, and the glob operator. For now, modules!
In this section, well talk about modules and other parts of the module system,
namely *paths* that allow you to name items; the `use` keyword that brings a
path into scope; and the `pub` keyword to make items public. Well also discuss
using the `as` keyword, external packages, and the glob operator. For now,
lets focus on modules!
*Modules* let us organize code within a crate into groups for readability and
easy re-use. Modules are also what control the *privacy* of items, which is
whether an item is allowed to be used by outside code (*public*) or whether
its an internal implementation detail and not available for outside use
(*private*).
easy reuse. Modules also control the *privacy* of items, which is whether an
item can be used by outside code (*public*) or whether its an internal
implementation detail and not available for outside use (*private*).
As an example, lets write a library crate that provides the functionality of a
restaurant. Were going to define the signatures of functions but leave their
bodies empty to concentrate on the organization of the code rather than
actually implementing a restaurant in code.
restaurant. Well define the signatures of functions but leave their bodies
empty to concentrate on the organization of the code rather than actually
implementing a restaurant in code.
In the restaurant industry, parts of a restaurant are referred to as *front of
house* and others as *back of house*. Front of house is where customers are,
and includes hosts seating customers, servers taking orders and payment, and
house* and others as *back of house*. Front of house is where customers are and
includes hosts seating customers, servers taking orders and payment, and
bartenders making drinks. Back of house includes the chefs and cooks in the
kitchen, dishwashers cleaning up, and managers doing administrative work.
To organize our crate in the same way that a real restaurant works, we can
To structure our crate in the same way that a real restaurant works, we can
organize the functions into nested modules. Create a new library named
`restaurant` by running `cargo new --lib restaurant`, then put the code in
`restaurant` by running `cargo new --lib restaurant`; then put the code in
Listing 7-1 into *src/lib.rs* to define some modules and function signatures.
<span class="filename">Filename: src/lib.rs</span>
@ -49,28 +48,28 @@ mod front_of_house {
```
<span class="caption">Listing 7-1: A `front_of_house` module containing other
modules which then contain functions</span>
modules that then contain functions</span>
We define a module by starting with the `mod` keyword, then specifying the name
of the module (in this case, `front_of_house`) and place curly brackets around
the body of the module. Inside modules, we can have other modules, as we have
in this case with the modules `hosting` and `serving`. Modules can also hold
definitions for other items such as structs, enums, constants, traits, or as
weve chosen in Listing 7-1, functions.
We define a module by starting with the `mod` keyword, and then specify the
name of the module (in this case, `front_of_house`) and place curly brackets
around the body of the module. Inside modules, we can have other modules, as in
this case with the modules `hosting` and `serving`. Modules can also hold
definitions for other items, such as structs, enums, constants, traits, or as
in Listing 7-1, functions.
By using modules, we can group related definitions together and name why
theyre related. Programmers using this code would have an easier time finding
the definitions they want to use because they could navigate the code based on
the groups rather than having to read through all the definitions. Programmers
working on this code tasked with adding new functionality would know where the
code should go in order to keep the program organized.
adding new functionality to this code would know where to place the code to
keep the program organized.
We mentioned in the “Packages and Crates” section that *src/main.rs* and
*src/lib.rs* are called *crate roots*. They are called crate roots because the
contents of either of these two files form a module named `crate` at the root
of the crates module structure, known as the *module tree*.
Earlier, we mentioned that *src/main.rs* and *src/lib.rs* are called *crate
roots*. The reason for their name is that the contents of either of these two
files form a module named `crate` at the root of the crates module structure,
known as the *module tree*.
Listing 7-2 shows the module tree for the structure in Listing 7-1:
Listing 7-2 shows the module tree for the structure in Listing 7-1.
```text
crate
@ -88,14 +87,15 @@ crate
7-1</span>
This tree shows how some of the modules nest inside one another (such as
`hosting` nests inside `front_of_house`) and how some modules are *siblings* to
each other, meaning they are defined in the same module (`hosting` and
`serving` are both defined within `front_of_house`). To continue the family
metaphor, if module A is contained inside module, we say say that module A is
the *child* of module B, and that module B is the *parent* of module A. Notice
that the entire module tree is rooted under the implicit module named `crate`.
`hosting` nests inside `front_of_house`). The tree also shows how some modules
are *siblings* to each other, meaning theyre defined in the same module
(`hosting` and `serving` are defined within `front_of_house`). To continue the
family metaphor, if module A is contained inside module B, we say that module A
is the *child* of module B, and that module B is the *parent* of module A.
Notice that the entire module tree is rooted under the implicit module named
`crate`.
The module tree might remind you of the directory tree of the filesystem you
have on your computer; this is a very apt comparison! Just like directories in
a filesystem, you use modules to organize your code. And just like files in a
directory, we need to have a way to find our modules.
The module tree might remind you of the filesystems directory tree on your
computer; this is a very apt comparison! Just like directories in a filesystem,
you use modules to organize your code. And just like files in a directory, we
need a way to find our modules.

View File

@ -1,8 +1,8 @@
## Paths for Referring to an Item in the Module Tree
To show Rust where to find an item in a module tree, we use a *path*, in the
same way that, when navigating a file system, we use a path. If we want to call
a function, we need to know its path.
To show Rust where to find an item in a module tree, we use a *path* in the
same way we use a path when navigating a filesystem. If we want to call a
function, we need to know its path.
A *path* can take two forms:
@ -14,12 +14,12 @@ A *path* can take two forms:
Both absolute and relative paths are followed by one or more identifiers
separated by double colons (`::`).
Lets return to our example in Listing 7-1. How do we call the
`add_to_waitlist` function? This is the same thing as asking, whats the path
of the `add_to_waitlist` function? In Listing 7-3, we simplified our code a bit
by removing some of the modules and functions. Well show two ways to call the
Lets return to the example in Listing 7-1. How do we call the
`add_to_waitlist` function? This is the same as asking, whats the path of the
`add_to_waitlist` function? In Listing 7-3, we simplified our code a bit by
removing some of the modules and functions. Well show two ways to call the
`add_to_waitlist` function from a new function `eat_at_restaurant` defined in
the crate root. Note that this example wont compile just yet, well explain
the crate root. Note that this example wont compile just yet; well explain
why in a bit.
<span class="filename">Filename: src/lib.rs</span>
@ -49,8 +49,8 @@ crate as `eat_at_restaurant`, which means we can use the `crate` keyword to
start an absolute path.
After `crate`, we include each of the successive modules until we make our way
to `add_to_waitlist`. You could imagine a file system with the same structure,
and wed specify the path `/front_of_house/hosting/add_to_waitlist` to run the
to `add_to_waitlist`. You can imagine a filesystem with the same structure, and
wed specify the path `/front_of_house/hosting/add_to_waitlist` to run the
`add_to_waitlist` program; using the `crate` name to start from the crate root
is like using `/` to start from the filesystem root in your shell.
@ -61,25 +61,20 @@ filesystem equivalent would be using the path
`front_of_house/hosting/add_to_waitlist`. Starting with a name means that the
path is relative.
<!--- Can you outline briefly what effect the path being relative or absolute
has on the code? I'm not totally clear why or when you'd use either --->
<!-- Done /Carol -->
Choosing whether to use a relative or absolute path is a decision youll make
based on your project. The decision should depend on whether youre more likely
to move item definition code separately from or together with the code that
uses the item. For example, if we move the `front_of_house` module and the
`eat_at_restaurant` function into a module named `customer_experience`, wed
need to update the absolute path to `add_to_waitlist`, but the relative path
would still be valid. However, if we moved the `eat_at_restaurant` function
separately into a module named `dining`, the absolute path to the
`add_to_waitlist` call would stay the same, but the relative path would need to
be updated. We tend to specify absolute paths because its more likely to move
code definitions and item calls independently of each other.
Choosing whether to use a relative or absolute paths is always a decision
youll have to make based on your specific project. It depends on whether
youre more likely to move code that defines items together or separately from
the code that uses the items. For example, if we move the `front_of_house`
module and the `eat_at_restaurant` function together into a module named
`customer_experience`, we would need to update the absolute path to
`add_to_waitlist` but the relative path would still be valid. However, if we
moved the `eat_at_restaurant` function separately into a module named `dining`,
the absolute path to the `add_to_waitlist` call would stay the same but the
relative path would need to be updated. We tend to specify absolute paths as
weve found that its more likely to move code definitions and item calls
independently of each other.
We mentioned that Listing 7-3 wont compile yet, lets try to compile it and
find out why not! The error we get is shown in Listing 7-4.
Lets try to compile Listing 7-3 and find out why it wont compile yet! The
error we get is shown in Listing 7-4.
```text
$ cargo build
@ -105,53 +100,33 @@ have the correct paths for the `hosting` module and the `add_to_waitlist`
function, but Rust wont let us use them because it doesnt have access to the
private sections.
<!-- Below: Can you define privacy boundary and say what it's useful for
briefly here? What does it mean for an item to be private? -->
<!-- Done /Carol -->
Modules are not only useful for organizing your code, they also define Rusts
*privacy boundary*, the line that encapsulates implementation details that
external code isnt allowed to know about, call, or rely on. Thus if you want
to make an item like a function or struct private, you put it in a module.
<!--- I didn't think we needed to have this as bullets, and likewise found the
up/down metaphor confusing. What do you think of this rewrite? --->
<!-- Pretty good, I took out the reference to "first" because there wasn't a
"second", etc anymore /Carol -->
Modules arent only useful for organizing your code, they also define Rusts
*privacy boundary*: the line that encapsulates the implementation details
external code isnt allowed to know about, call, or rely on. So, if you want to
make an item like a function or struct private, you put it in a module.
The way privacy works in Rust is that all items (functions, methods, structs,
enums, modules, and constants) are private by default. Items in a parent module
cant use the private items inside child modules, while items in child modules
can use the items in their ancestor modules. This is because child modules wrap
and hide their implementation details, but the child modules can see the
cant use the private items inside child modules, but items in child modules
can use the items in their ancestor modules. The reason is that child modules
wrap and hide their implementation details, but the child modules can see the
context in which theyre defined. To continue with the restaurant metaphor,
think of the privacy rules like the back office of a restaurant: what goes on
in there is private to customers of the restaurant, but managers in the office
can see and do everything in the restaurant in which they operate.
<!-- above: Is this line I added true? Can you quickly say why the child can
access the parent but not the other way round? -->
<!-- I've tried to explain and use the metaphor, how's this? /Carol -->
in there is private to restaurant customers, but office managers can see and do
everything in the restaurant in which they operate.
Rust chose to have the module system function this way so that hiding inner
implementation details is the default. That way, you know which parts of the
inner code you can change without the possibility of breaking outer code.
However, you can consciously choose to expose inner parts of child modules code
to outer ancestor modules by making an item public with the `pub` keyword.
inner code you can change without breaking outer code. But you can expose inner
parts of child modules code to outer ancestor modules by making an item public
using the `pub` keyword.
### Exposing Paths with the `pub` Keyword
<!-- I'm not sure this is an accurate heading, can you fix it? I wanted to
expand a little to show its relation to the path topics that surround it-->
<!-- It's less about who on the outside gains access to it, and more about who
on the inside chooses to expose it. How's this heading, in light of that?
/Carol -->
With that understanding, lets look back at the error in Listing 7-4, that told
us the `hosting` module is private. We want the `eat_at_restaurant` function in
the parent module to have access to the `add_to_waitlist` function in the child
module, so we mark the `hosting` module with the `pub` keyword, shown in
Listing 7-5.
Lets return to the error in Listing 7-4 that told us the `hosting` module is
private. We want the `eat_at_restaurant` function in the parent module to have
access to the `add_to_waitlist` function in the child module, so we mark the
`hosting` module with the `pub` keyword, as shown in Listing 7-5.
<span class="filename">Filename: src/lib.rs</span>
@ -171,11 +146,11 @@ pub fn eat_at_restaurant() {
}
```
<span class="caption">Listing 7-5: Declaring the `hosting` module as `pub` so
that were allowed to use it from `eat_at_restaurant`</span>
<span class="caption">Listing 7-5: Declaring the `hosting` module as `pub` to
use it from `eat_at_restaurant`</span>
Unfortunately, as you may have just found out, the code in Listing 7-5 still
results in an error (Listing 7-6):
Unfortunately, the code in Listing 7-5 still results in an error, as shown in
Listing 7-6.
```text
$ cargo build
@ -197,17 +172,17 @@ error[E0603]: function `add_to_waitlist` is private
Listing 7-5</span>
What happened? Adding the `pub` keyword in front of `mod hosting` makes the
module public. With this change, if were allowed to access `front_of_house`,
we can access `hosting`. But the *contents* of `hosting` are still private;
making the module public does not make its contents public. The `pub` keyword
on a module only lets code in its ancestor modules refer to it.
module public. With this change, if we can access `front_of_house`, we can
access `hosting`. But the *contents* of `hosting` are still private; making the
module public doesnt make its contents public. The `pub` keyword on a module
only lets code in its ancestor modules refer to it.
The errors in Listing 7-6 now say that the `add_to_waitlist` function is
private. The privacy rules apply to structs, enums, functions, and methods as
well as modules.
The errors in Listing 7-6 say that the `add_to_waitlist` function is private.
The privacy rules apply to structs, enums, functions, and methods as well as
modules.
Lets also make the `add_to_waitlist` function public by adding the `pub`
keyword before its definition, as in Listing 7-7:
keyword before its definition, as in Listing 7-7.
<span class="filename">Filename: src/lib.rs</span>
@ -228,50 +203,42 @@ pub fn eat_at_restaurant() {
# fn main() {}
```
<span class="caption">Listing 7-7: Adding the `pub` keyword to both `mod
hosting` and `fn add_to_waitlist` lets us call the function from
<span class="caption">Listing 7-7: Adding the `pub` keyword to `mod hosting`
and `fn add_to_waitlist` lets us call the function from
`eat_at_restaurant`</span>
Now itll compile! Lets look at both the absolute and the relative path and
double check why adding the `pub` keyword lets us use these paths in
Now the code will compile! Lets look at the absolute and the relative path,
and double-check why adding the `pub` keyword lets us use these paths in
`add_to_waitlist` with respect to the privacy rules.
<!---
is a crate the same as a "module tree"? what does it mean to be the root of the
crate. --->
<!-- A crate has a module tree; a module tree is the structure of the crate.
I'm not sure how to clarify that here? I thought crate/root/module tree was
explained sufficiently earlier /Carol -->
In the absolute path, we start with `crate`, the root of our crates module
tree. Then the `front_of_house` module is defined in the crate root. The
`front_of_house` module isnt public, but because the `eat_at_restaurant`
function is defined in the same module as `front_of_house` (that is,
`eat_at_restaurant` and `front_of_house` are siblings), we can refer to
`front_of_house` from `eat_at_restaurant`. Next is the `hosting` module marked
with `pub`. We can access the parent module of `hosting`, so we can access
`hosting`. Finally, the `add_to_waitlist` function is marked with `pub` and we
can access its parent module, so this function call works!
In the absolute path case, we start with `crate`, the root of our crates
module tree. From here, we have the `front_of_house` module defined in the
crate root. The `front_of_house` module isnt public, but because the
`eat_at_restaurant` function is defined in the same module that
`front_of_house` is defined (that is, `eat_at_restaurant` and `front_of_house`
are siblings), were allowed to refer to `front_of_house` from
`eat_at_restaurant`. Next is the `hosting` module marked with `pub`. We can
access the parent module of `hosting`, so were allowed to access `hosting`.
Finally, the `add_to_waitlist` function is marked with `pub` and we can access
its parent module, so this function call works!
In the relative path case, the logic is the same as the absolute path except
for the first step: rather than starting from the crate root, the path starts
from `front_of_house`. The `front_of_house` module is defined within the same
module as `eat_at_restaurant`, so the relative path starting from the module in
which `eat_at_restaurant` is defined works. Then because `hosting` and
In the relative path, the logic is the same as the absolute path except for the
first step: rather than starting from the crate root, the path starts from
`front_of_house`. The `front_of_house` module is defined within the same module
as `eat_at_restaurant`, so the relative path starting from the module in which
`eat_at_restaurant` is defined works. Then, because `hosting` and
`add_to_waitlist` are marked with `pub`, the rest of the path works and this
function call is valid!
### Starting Relative Paths with `super`
You can also construct relative paths that begin in the parent module by using
We can also construct relative paths that begin in the parent module by using
`super` at the start of the path. This is like starting a filesystem path with
`..`. Why would we want to do this?
the `..` syntax. Why would we want to do this?
Consider the situation in Listing 7-8 that models the case where a chef fixes
an incorrect order and personally brings it out to the customer. The function
`fix_incorrect_order` calls the function `serve_order` by specifying the path
to `serve_order` starting with `super`:
Consider the code in Listing 7-8 that models the situation in which a chef
fixes an incorrect order and personally brings it out to the customer. The
function `fix_incorrect_order` calls the function `serve_order` by specifying
the path to `serve_order` starting with `super`:
<span class="filename">Filename: src/lib.rs</span>
@ -298,27 +265,21 @@ is `crate`, the root. From there, we look for `serve_order` and find it.
Success! We think the `back_of_house` module and the `serve_order` function are
likely to stay in the same relationship to each other and get moved together
should we decide to reorganize the crates module tree. Therefore, we used
`super` so that well have fewer places to update code in the future, should
this code get moved to a different module.
<!-- Can you broaden this out and let them know the general reason we would use
super over the other methods here? -->
<!-- The reason we have here *is* the general reason, I'm not sure what about
the text implies that there's a broader reason we aren't mentioning? /Carol -->
`super` so well have fewer places to update code in the future if this code
gets moved to a different module.
### Making Structs and Enums Public
You can also use `pub` to designate structs and enums as public, but there are
a few extra details. If you use `pub` before a struct definition, you make the
struct public, but the structs fields will still be private. You can choose to
make each field public or not on a case-by-case basis. In Listing 7-9, weve
defined a public `back_of_house::Breakfast` struct with a public `toast` field
but a private `seasonal_fruit` field. This models the case in a restaurant
where the customer can pick the type of bread that comes with a meal, but the
chef decides what fruit will come with a meal based on whats in season and
what they have in stock. The fruit thats available changes quickly so
customers arent allowed to choose the fruit or even see which fruit theyll
get.
We can also use `pub` to designate structs and enums as public, but there are a
few extra details. If we use `pub` before a struct definition, we make the
struct public, but the structs fields will still be private. We can make each
field public or not on a case-by-case basis. In Listing 7-9, weve defined a
public `back_of_house::Breakfast` struct with a public `toast` field but a
private `seasonal_fruit` field. This models the case in a restaurant where the
customer can pick the type of bread that comes with a meal, but the chef
decides which fruit accompanies the meal based on whats in season and in
stock. The available fruit changes quickly, so customers cant choose the fruit
or even see which fruit theyll get.
<span class="filename">Filename: src/lib.rs</span>
@ -355,22 +316,21 @@ pub fn eat_at_restaurant() {
<span class="caption">Listing 7-9: A struct with some public fields and some
private fields</span>
Because the `toast` field of the `back_of_house::Breakfast` struct is public,
Because the `toast` field in the `back_of_house::Breakfast` struct is public,
in `eat_at_restaurant` we can write and read to the `toast` field using dot
notation. Notice, though, that were not allowed to use the `seasonal_fruit`
field in `eat_at_restaurant` because `seasonal_fruit` is private. Try
uncommenting the line modifying the `seasonal_fruit` field value to see what
error you get!
notation. Notice that we cant use the `seasonal_fruit` field in
`eat_at_restaurant` because `seasonal_fruit` is private. Try uncommenting the
line modifying the `seasonal_fruit` field value to see what error you get!
Also note that because `back_of_house::Breakfast` has a private field, the
Also, note that because `back_of_house::Breakfast` has a private field, the
struct needs to provide a public associated function that constructs an
instance of `Breakfast` (weve named it `summer` here). If `Breakfast` didnt
have such a function, we wouldnt be able to create an instance of `Breakfast`
in `eat_at_restaurant` because were not allowed to set the value of the
private `seasonal_fruit` field in `eat_at_restaurant`.
have such a function, we couldnt create an instance of `Breakfast` in
`eat_at_restaurant` because we cant set the value of the private
`seasonal_fruit` field in `eat_at_restaurant`.
In contrast, if you make an enum public, all of its variants are then public.
You only need the `pub` before the `enum` keyword, as shown in Listing 7-10.
In contrast, if we make an enum public, all of its variants are then public. We
only need the `pub` before the `enum` keyword, as shown in Listing 7-10.
<span class="filename">Filename: src/lib.rs</span>
@ -391,18 +351,13 @@ pub fn eat_at_restaurant() {
<span class="caption">Listing 7-10: Designating an enum as public makes all its
variants public</span>
<!-- Is there a reason rust developers chose to have enum arms public but the
content of structs not, using pub? -->
<!-- Added! /Carol -->
Because we made the `Appetizer` enum public, we can use the `Soup` and `Salad`
variants in `eat_at_restaurant`. Enums arent very useful unless their variants
are public; it would be annoying to have to annotate all enum variants with
`pub` in every case, so the default for enum variants is to be public. Structs
are often useful without their fields being public, so struct fields follow the
general rule of everything being private by default unless annotated with `pub`.
Because we made the `Appetizer` enum public, were able to use the `Soup` and
`Salad` variants in `eat_at_restaurant`. Enums arent very useful unless their
variants are public; it would be annoying to have to annotate all enum variants
with `pub` in every case, so the default for enum variants is to be public.
Structs are often useful without their fields being public, so struct fields
follow the general rule of everything being private by default unless annotated
with `pub`.
Theres one more situation involving `pub` that we havent covered, and that
concerns our last module system feature: the `use` keyword. Lets cover `use`
by itself first, and then well show how `pub` and `use` can be combined.
Theres one more situation involving `pub` that we havent covered, and that is
our last module system feature: the `use` keyword. Well cover `use` by itself
first, and then well show how to combine `pub` and `use`.

View File

@ -1,18 +1,15 @@
## Bringing Paths into Scope with the `use` Keyword
<!-- Liz: All the subsections of this section have to do with `use`, so they
should be HeadC rather than HeadB as you had them. /Carol -->
It may seem like the paths weve written to call functions so far are
It might seem like the paths weve written to call functions so far are
inconveniently long and repetitive. For example, in Listing 7-7, whether we
chose the absolute or relative path to the `add_to_waitlist` function, every
time we wanted to call `add_to_waitlist` we had to specify `front_of_house` and
`hosting` too. Luckily, theres a way to simplify this process. We can bring a
path into a scope once and then call the items in that path as if theyre local
items with the `use` keyword.
`hosting` too. Fortunately, theres a way to simplify this process. We can
bring a path into a scope once and then call the items in that path as if
theyre local items with the `use` keyword.
In Listing 7-11, we bring the `crate::front_of_house::hosting` module into the
scope of the `eat_at_restaurant` function so that we only have to specify
scope of the `eat_at_restaurant` function so we only have to specify
`hosting::add_to_waitlist` to call the `add_to_waitlist` function in
`eat_at_restaurant`.
@ -40,12 +37,12 @@ pub fn eat_at_restaurant() {
Adding `use` and a path in a scope is similar to creating a symbolic link in
the filesystem. By adding `use crate::front_of_house::hosting` in the crate
root, `hosting` is now a valid name in that scope, just as if the `hosting`
root, `hosting` is now a valid name in that scope, just as though the `hosting`
module had been defined in the crate root. Paths brought into scope with `use`
also check privacy, like any other paths.
Specifying a relative path with `use` is slightly different. Instead of
starting from a name in the current scope, you must start the path given to
starting from a name in the current scope, we must start the path given to
`use` with the keyword `self`. Listing 7-12 shows how to specify a relative
path to get the same behavior as Listing 7-11.
@ -72,18 +69,14 @@ pub fn eat_at_restaurant() {
a relative path starting with `self`</span>
Note that using `self` in this way might not be necessary in the future; its
an inconsistency in the language that Rust developers are working on
eliminating.
an inconsistency in the language that Rust developers are working to eliminate.
### Creating Idiomatic `use` Paths
In Listing 7-11, you may have wondered why we specified `use
In Listing 7-11, you might have wondered why we specified `use
crate::front_of_house::hosting` and then called `hosting::add_to_waitlist` in
`eat_at_restaurant`, rather than specifying the `use` path all the way out to
the add_to_waitlist function to achieve the same result, as in Listing 7-13:
<!-- Can you specify what we're doing differently here? -->
<!-- Done /Carol -->
`eat_at_restaurant` rather than specifying the `use` path all the way out to
the `add_to_waitlist` function to achieve the same result, as in Listing 7-13.
<span class="filename">Filename: src/lib.rs</span>
@ -107,12 +100,12 @@ pub fn eat_at_restaurant() {
<span class="caption">Listing 7-13: Bringing the `add_to_waitlist` function
into scope with `use`, which is unidiomatic</span>
While both Listing 7-11 and 7-13 accomplish the same thing, Listing 7-11 is the
idiomatic way to bring a function into scope with `use`. Bringing the
Although both Listing 7-11 and 7-13 accomplish the same task, Listing 7-11 is
the idiomatic way to bring a function into scope with `use`. Bringing the
functions parent module into scope with `use` so we have to specify the parent
module when calling the function makes it clear that the function isnt locally
defined, while still minimizing repetition of the full path. The code in
Listing 7-13 is unclear as to where `add_to_waitlist` is defined.
defined while still minimizing repetition of the full path. The code in Listing
7-13 is unclear as to where `add_to_waitlist` is defined.
On the other hand, when bringing in structs, enums, and other items with `use`,
its idiomatic to specify the full path. Listing 7-14 shows the idiomatic way
@ -133,14 +126,13 @@ fn main() {
<span class="caption">Listing 7-14: Bringing `HashMap` into scope in an
idiomatic way</span>
Theres no strong reason behind this idiom; this is just the convention that
has emerged, and folks have gotten used to reading and writing Rust code this
way.
Theres no strong reason behind this idiom: its just the convention that has
emerged, and folks have gotten used to reading and writing Rust code this way.
The exception to this idiom is if you are bringing two items with the same name
into scope with `use` statements, as Rust doesnt allow that. Listing 7-15
The exception to this idiom is if were bringing two items with the same name
into scope with `use` statements, because Rust doesnt allow that. Listing 7-15
shows how to bring two `Result` types into scope that have the same name but
different parent modules, and how to refer to them.
different parent modules and how to refer to them.
<span class="filename">Filename: src/lib.rs</span>
@ -158,7 +150,7 @@ fn function2() -> io::Result<()> {
```
<span class="caption">Listing 7-15: Bringing two types with the same name into
the same scope requires using their parent modules</span>
the same scope requires using their parent modules.</span>
As you can see, using the parent modules distinguishes the two `Result` types.
If instead we specified `use std::fmt::Result` and `use std::io::Result`, wed
@ -170,7 +162,7 @@ meant when we used `Result`. Try it and see what compiler error you get!
Theres another solution to the problem of bringing two types of the same name
into the same scope with `use`: after the path, we can specify `as` and a new
local name, or alias, for the type. Listing 7-16 shows another way to write the
code from Listing 7-15 by renaming one of the two `Result` types using `as`.
code in Listing 7-15 by renaming one of the two `Result` types using `as`.
<span class="filename">Filename: src/lib.rs</span>
@ -192,25 +184,20 @@ scope with the `as` keyword</span>
In the second `use` statement, we chose the new name `IoResult` for the
`std::io::Result` type, which wont conflict with the `Result` from `std::fmt`
that weve also brought into scope. Both Listing 7-15 and Listing 7-16 are
considered idiomatic, the choice is up to you!
that weve also brought into scope. Listing 7-15 and Listing 7-16 are
considered idiomatic, so the choice is up to you!
### Re-exporting Names with `pub use`
<!--- I found this paragraph a little difficult to follow and have tried to
clarify -- can you please check my edits and correct anywhere I may have
changed meaning? --->
<!-- Looks fine! /Carol -->
When you bring a name into scope with the `use` keyword, the name available in
the new scope is private. To enable the code that calls your code to refer to
that name as if it had been defined in that codes scope, you can combine `pub`
and `use`. This technique is called *re-exporting* because youre bringing an
item into scope but also making that item available for others to bring into
When we bring a name into scope with the `use` keyword, the name available in
the new scope is private. To enable the code that calls our code to refer to
that name as if it had been defined in that codes scope, we can combine `pub`
and `use`. This technique is called *re-exporting* because were bringing
an item into scope but also making that item available for others to bring into
their scope.
Listing 7-17 shows the code from Listing 7-11 with the `use` in the
root module changed to `pub use`.
Listing 7-17 shows the code in Listing 7-11 with `use` in the root module
changed to `pub use`.
<span class="filename">Filename: src/lib.rs</span>
@ -236,23 +223,23 @@ from a new scope with `pub use`</span>
By using `pub use`, external code can now call the `add_to_waitlist` function
using `hosting::add_to_waitlist`. If we hadnt specified `pub use`, the
`eat_at_restaurant` function can call `hosting::add_to_waitlist` in its scope
but external code wouldnt be allowed to take advantage of this new path.
`eat_at_restaurant` function could call `hosting::add_to_waitlist` in its scope
but external code couldnt take advantage of this new path.
This is useful when the internal structure of your code is different than the
way programmers calling your code would think about the domain. For example, in
this restaurant metaphor, the people running the restaurant think about “front
of house” and “back of house” but customers visiting a restaurant probably
wont think about the parts of the restaurant in those terms. With `pub use`,
we can write our code with one structure but expose a different structure to
make our library well organized both for programmers working on the library and
programmers calling the library.
Re-exporting is useful when the internal structure of your code is different
than the way programmers calling your code would think about the domain. For
example, in this restaurant metaphor, the people running the restaurant think
about “front of house” and “back of house.” But customers visiting a restaurant
probably wont think about the parts of the restaurant in those terms. With
`pub use`, we can write our code with one structure but expose a different
structure. Doing so makes our library well organized for programmers working on
the library and programmers calling the library.
### Using External Packages
In Chapter 2 we programmed a guessing game project that used an external
package, `rand`, to get random numbers. To use `rand` in our project, we added
this line to *Cargo.toml*:
In Chapter 2, we programmed a guessing game project that used an external
package called `rand` to get random numbers. To use `rand` in our project, we
added this line to *Cargo.toml*:
<span class="filename">Filename: Cargo.toml</span>
@ -267,9 +254,9 @@ available to our project.
Then, to bring `rand` definitions into the scope of our package, we added a
`use` line starting with the name of the package, `rand`, and listing the items
we wanted to bring into scope. Recall that in the [“Generating a Random
Number”][rand]<!-- ignore --> section in Chapter 2, we brought the `Rng` trait
into scope and called the `rand::thread_rng` function:
we wanted to bring into scope. Recall that in the section [“Generating a Random
Number”][rand]<!-- ignore --> in Chapter 2, we brought the `Rng` trait into
scope and called the `rand::thread_rng` function:
```rust,ignore
use rand::Rng;
@ -279,15 +266,15 @@ fn main() {
```
Members of the Rust community have made many packages available at
*https://crates.io*, and pulling any of them in to your package involves these
same steps: listing them in your packages *Cargo.toml* and using `use` to
*https://crates.io*, and pulling any of them into your package involves these
same steps: listing them in your packages *Cargo.toml* file and using `use` to
bring items into scope.
Note that the standard library (`std`) is also a crate thats external to your
package. Because the standard library is shipped with the Rust language, you
dont need to change *Cargo.toml* to include `std`, but you do need to refer to
it with `use` to bring items from there into your packages scope. For example,
with `HashMap`:
Note that the standard library (`std`) is also a crate thats external to our
package. Because the standard library is shipped with the Rust language, we
dont need to change *Cargo.toml* to include `std`. But we do need to refer to
it with `use` to bring items from there into our packages scope. For example,
with `HashMap` we would use this line:
```rust
use std::collections::HashMap;
@ -298,10 +285,10 @@ crate.
### Using Nested Paths to Clean Up Large `use` Lists
If youre using multiple items defined in the same package or same module,
listing each item on its own line can take up a lot of vertical space in your
If were using multiple items defined in the same package or same module,
listing each item on its own line can take up a lot of vertical space in our
files. For example, these two `use` statements we had in Listing 2-4 in the
Guessing Game both bring items from `std` into scope:
Guessing Game bring items from `std` into scope:
<span class="filename">Filename: src/main.rs</span>
@ -311,10 +298,10 @@ use std::io;
// ---snip---
```
Instead, we can use nested paths to bring the same items into scope in one line.
We do this by specifying the common part of the path, then two colons, then
curly brackets around a list of the parts of the paths that differ, as shown in
Listing 7-18.
Instead, we can use nested paths to bring the same items into scope in one
line. We do this by specifying the common part of the path, followed by two
colons, and then curly brackets around a list of the parts of the paths that
differ, as shown in Listing 7-18.
<span class="filename">Filename: src/main.rs</span>
@ -330,14 +317,10 @@ In bigger programs, bringing many items into scope from the same package or
module using nested paths can reduce the number of separate `use` statements
needed by a lot!
<!--- Below: is this what you meant? I found deduplicate to be a confusing
word, if that's a technical term, please revert these changes. --->
<!-- This is fine /Carol -->
You can use a nested path at any level in a path, which is useful when
combining two `use` statements that share a subpath. For example, Listing 7-19
shows two `use` statements: one that brings `std::io` into scope and one that
brings `std::io::Write` into scope:
We can use a nested path at any level in a path, which is useful when combining
two `use` statements that share a subpath. For example, Listing 7-19 shows two
`use` statements: one that brings `std::io` into scope and one that brings
`std::io::Write` into scope.
<span class="filename">Filename: src/lib.rs</span>
@ -346,12 +329,12 @@ use std::io;
use std::io::Write;
```
<span class="caption">Listing 7-19: Two `use` statements where one is a
sub-path of the other</span>
<span class="caption">Listing 7-19: Two `use` statements where one is a subpath
of the other</span>
The common part of these two paths is `std::io`, and thats the complete first
path. To merge these two paths into one `use` statement, we can use `self` in
the nested path as shown in Listing 7-20.
the nested path, as shown in Listing 7-20.
<span class="filename">Filename: src/lib.rs</span>
@ -359,32 +342,31 @@ the nested path as shown in Listing 7-20.
use std::io::{self, Write};
```
<span class="caption">Listing 7-20: Combining the paths from Listing 7-19 into
<span class="caption">Listing 7-20: Combining the paths in Listing 7-19 into
one `use` statement</span>
This brings both `std::io` and `std::io::Write` into scope.
This line brings `std::io` and `std::io::Write` into scope.
### The Glob Operator
If youd like to bring *all* public items defined in a path into scope, you can
If we want to bring *all* public items defined in a path into scope, we can
specify that path followed by `*`, the glob operator:
```rust
use std::collections::*;
```
This `use` statement brings all public items defined in `std::collections`
into the current scope. Be careful when using the glob operator! Glob can make
it harder to tell what names are in scope and where a name used in your program
This `use` statement brings all public items defined in `std::collections` into
the current scope. Be careful when using the glob operator! Glob can make it
harder to tell what names are in scope and where a name used in your program
was defined.
The glob operator is often used when testing to bring everything under test
into the `tests` module; well talk about that in the [“How to Write
Tests”][writing-tests]<!-- ignore --> section of Chapter 11. The glob operator
is also sometimes used as part of the prelude pattern; see [the standard
library documentation](../std/prelude/index.html#other-preludes)<!-- ignore -->
for more information on that pattern.
into the `tests` module; well talk about that in the section [“How to Write
Tests”][writing-tests]<!-- ignore --> in Chapter 11. The glob operator is also
sometimes used as part of the prelude pattern: see [the standard library
documentation](../std/prelude/index.html#other-preludes)<!-- ignore --> for
more information on that pattern.
[packages]: ch07-01-packages-and-crates-for-making-libraries-and-executables.html#packages-and-crates-for-making-libraries-and-executables
[rand]: ch02-00-guessing-game-tutorial.html#generating-a-random-number
[writing-tests]: ch11-01-writing-tests.html#how-to-write-tests

View File

@ -1,14 +1,14 @@
## Separating Modules into Different Files
So far, all of the examples in this chapter defined multiple modules in one
file. When modules get large, you may want to move their definitions to a
separate file to make the code easier to navigate.
So far, all the examples in this chapter defined multiple modules in one file.
When modules get large, you might want to move their definitions to a separate
file to make the code easier to navigate.
For example, lets take the code in Listing 7-17 and move the `front_of_house`
module to its own file *src/front_of_house.rs* by changing the crate root file
so that it contains the code shown in Listing 7-21. In this case, the crate
root file is *src/lib.rs*, but this procedure works with binary crates whose
crate root file is *src/main.rs* too.
For example, lets start from the code in Listing 7-17 and move the
`front_of_house` module to its own file *src/front_of_house.rs* by changing the
crate root file so it contains the code shown in Listing 7-21. In this case,
the crate root file is *src/lib.rs*, but this procedure also works with binary
crates whose crate root file is *src/main.rs*.
<span class="filename">Filename: src/lib.rs</span>
@ -28,7 +28,7 @@ pub fn eat_at_restaurant() {
body will be in *src/front_of_house.rs*</span>
And *src/front_of_house.rs* gets the definitions from the body of the
`front_of_house` module, shown in Listing 7-22.
`front_of_house` module, as shown in Listing 7-22.
<span class="filename">Filename: src/front_of_house.rs</span>
@ -41,7 +41,7 @@ pub mod hosting {
<span class="caption">Listing 7-22: Definitions inside the `front_of_house`
module in *src/front_of_house.rs*</span>
Using a semicolon after `mod front_of_house`, rather than using a block, tells
Using a semicolon after `mod front_of_house` rather than using a block tells
Rust to load the contents of the module from another file with the same name as
the module. To continue with our example and extract the `hosting` module to
its own file as well, we change *src/front_of_house.rs* to contain only the
@ -63,13 +63,14 @@ Then we create a *src/front_of_house* directory and a file
pub fn add_to_waitlist() {}
```
The module tree remains the same and the function calls in `eat_at_restaurant`
The module tree remains the same, and the function calls in `eat_at_restaurant`
will work without any modification, even though the definitions live in
different files. This lets you move modules to new files as they grow in size.
different files. This technique lets you move modules to new files as they grow
in size.
Note that the `pub use crate::front_of_house::hosting` statement in
*src/lib.rs* also hasnt changed, nor does `use` have any impact on what files
are compiled as part of the crate. The `mod` keyword declares modules and Rust
are compiled as part of the crate. The `mod` keyword declares modules, and Rust
looks in a file with the same name as the module for the code that goes into
that module.
@ -78,9 +79,10 @@ that module.
Rust lets you organize your packages into crates and your crates into modules
so you can refer to items defined in one module from another module. You can do
this by specifying absolute or relative paths. These paths can be brought into
scope with a `use` statement so that you can use a shorter path for multiple
uses of the item in that scope. Module code is private by default, but you can
choose to make definitions public by adding the `pub` keyword.
scope with a `use` statement so you can use a shorter path for multiple uses of
the item in that scope. Module code is private by default, but you can make
definitions public by adding the `pub` keyword.
In the next chapter, well look at some collection data structures in the
standard library that you can use in your nice, neatly organized code.
standard library that you can use in your neatly organized code.

View File

@ -808,10 +808,9 @@ figuring out where our bug is!
### Using `Result<T, E>` in Tests
So far, weve written tests that fail when code within the test panics. We can
also write tests that use `Result<T, E>` and fail when code within the test
returns the `Err` variant! Heres the test from Listing 11-1, rewritten to use
`Result<T, E>` instead of panicking:
So far, weve written tests that panic when they fail. We can also write tests
that use `Result<T, E>`! Heres the test from Listing 11-1, rewritten to use
`Result<T, E>` and return an `Err` instead of panicking:
```rust
#[cfg(test)]
@ -830,9 +829,11 @@ mod tests {
The `it_works` function now has a return type, `Result<(), String>`. In the
body of the function, rather than calling the `assert_eq!` macro, we return
`Ok(())` when the test passes and an `Err` with a `String` inside when the test
fails. Writing tests that return a `Result<T, E>` enables you to use the `?`
operator in the body of tests, which can be a convenient way to write tests
that should fail if any operation within them returns an `Err` variant.
fails.
Writing tests so they return a `Result<T, E>` enables you to use the question
mark operator in the body of tests, which can be a convenient way to write
tests that should fail if any operation within them returns an `Err` variant.
You cant use the `#[should_panic]` annotation on tests that use `Result<T,
E>`. Instead, you should return an `Err` value directly when the test should

View File

@ -326,11 +326,11 @@ matching.
#### Destructuring Nested Structs and Enums
Up until now, all of our examples have been matching structs or enums that were
one level deep. Matching can work on nested items too!
Until now, all our examples have been matching structs or enums that were one
level deep. Matching can work on nested items too!
For example, we can refactor the code in Listing 18-15 to support both RGB and
HSV colors in the `ChangeColor` message, as shown in Listing 18-16.
For example, we can refactor the code in Listing 18-15 to support RGB and HSV
colors in the `ChangeColor` message, as shown in Listing 18-16.
```rust
enum Color {
@ -373,11 +373,11 @@ fn main() {
<span class="caption">Listing 18-16: Matching on nested enums</span>
The pattern of the first arm in the `match` expression matches a
`Message::ChangeColor` enum variant that contains a `Color::Rgb` variant, and
then the pattern binds to the three inner `i32` values. The pattern of the
second arm also matches a `Message::ChangeColor` enum variant, but the inner
enum matches the `Color::Hsv` variant instead. We can specify these complex
conditions in one `match` expression even though two enums are involved.
`Message::ChangeColor` enum variant that contains a `Color::Rgb` variant; then
the pattern binds to the three inner `i32` values. The pattern of the second
arm also matches a `Message::ChangeColor` enum variant, but the inner enum
matches the `Color::Hsv` variant instead. We can specify these complex
conditions in one `match` expression, even though two enums are involved.
#### Destructuring Structs and Tuples