mirror of https://github.com/rust-lang/book
Compare commits
3 Commits
d207d894cc
...
cb0a24007f
Author | SHA1 | Date |
---|---|---|
Carol (Nichols || Goulding) | cb0a24007f | |
Carol (Nichols || Goulding) | f954cb859f | |
Carol (Nichols || Goulding) | 98165c4279 |
|
@ -20,7 +20,7 @@ optionally one library crate. As a package grows, you can extract parts into
|
||||||
separate crates that become external dependencies. This chapter covers all
|
separate crates that become external dependencies. This chapter covers all
|
||||||
these techniques. For very large projects comprising a set of interrelated
|
these techniques. For very large projects comprising a set of interrelated
|
||||||
packages that evolve together, Cargo provides *workspaces*, which we’ll cover
|
packages that evolve together, Cargo provides *workspaces*, which we’ll cover
|
||||||
in “Cargo Workspaces” on page XX.
|
in the “Cargo Workspaces” section in Chapter 14.
|
||||||
|
|
||||||
We’ll also discuss encapsulating implementation details, which lets you reuse
|
We’ll also discuss encapsulating implementation details, which lets you reuse
|
||||||
code at a higher level: once you’ve implemented an operation, other code can
|
code at a higher level: once you’ve implemented an operation, other code can
|
||||||
|
@ -43,11 +43,11 @@ organization, including which details are exposed, which details are private,
|
||||||
and what names are in each scope in your programs. These features, sometimes
|
and what names are in each scope in your programs. These features, sometimes
|
||||||
collectively referred to as the *module system*, include:
|
collectively referred to as the *module system*, include:
|
||||||
|
|
||||||
* **Packages **: A Cargo feature that lets you build, test, and share crates
|
* **Packages:** A Cargo feature that lets you build, test, and share crates
|
||||||
* **Crates**: A tree of modules that produces a library or executable
|
* **Crates:** A tree of modules that produces a library or executable
|
||||||
* **Modules and use**: Let you control the organization, scope, and privacy of
|
* **Modules** and **use:** Let you control the organization, scope, and
|
||||||
paths
|
privacy of paths
|
||||||
* **Paths **: A way of naming an item, such as a struct, function, or module
|
* **Paths:** A way of naming an item, such as a struct, function, or module
|
||||||
|
|
||||||
In this chapter, we’ll cover all these features, discuss how they interact, and
|
In this chapter, we’ll 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
|
explain how to use them to manage scope. By the end, you should have a solid
|
||||||
|
@ -59,35 +59,36 @@ The first parts of the module system we’ll cover are packages and crates.
|
||||||
|
|
||||||
A *crate* is the smallest amount of code that the Rust compiler considers at a
|
A *crate* is the smallest amount of code that the Rust compiler considers at a
|
||||||
time. Even if you run `rustc` rather than `cargo` and pass a single source code
|
time. Even if you run `rustc` rather than `cargo` and pass a single source code
|
||||||
file (as we did all the way back in “Writing and Running a Rust Program” on
|
file (as we did all the way back in the “Writing and Running a Rust Program”
|
||||||
page XX), the compiler considers that file to be a crate. Crates can contain
|
section of Chapter 1), the compiler considers that file to be a crate. Crates
|
||||||
modules, and the modules may be defined in other files that get compiled with
|
can contain modules, and the modules may be defined in other files that get
|
||||||
the crate, as we’ll see in the coming sections.
|
compiled with the crate, as we’ll see in the coming sections.
|
||||||
|
|
||||||
A crate can come in one of two forms: a binary crate or a library crate.
|
A crate can come in one of two forms: a binary crate or a library crate.
|
||||||
*Binary crates* are programs you can compile to an executable that you can run,
|
*Binary crates* are programs you can compile to an executable that you can run,
|
||||||
such as a command line program or a server. Each must have a function called
|
such as a command-line program or a server. Each must have a function called
|
||||||
`main` that defines what happens when the executable runs. All the crates we’ve
|
`main` that defines what happens when the executable runs. All the crates we’ve
|
||||||
created so far have been binary crates.
|
created so far have been binary crates.
|
||||||
|
|
||||||
*Library crates* don’t have a `main` function, and they don’t compile to an
|
*Library crates* don’t have a `main` function, and they don’t compile to an
|
||||||
executable. Instead, they define functionality intended to be shared with
|
executable. Instead, they define functionality intended to be shared with
|
||||||
multiple projects. For example, the `rand` crate we used in Chapter 2 provides
|
multiple projects. For example, the `rand` crate we used in Chapter
|
||||||
functionality that generates random numbers. Most of the time when Rustaceans
|
2 provides functionality that generates random numbers.
|
||||||
say “crate,” they mean library crate, and they use “crate” interchangeably with
|
Most of the time when Rustaceans say “crate”, they mean library crate, and they
|
||||||
the general programming concept of a “library.”
|
use “crate” interchangeably with the general programming concept of a “library".
|
||||||
|
|
||||||
The *crate root* is a source file that the Rust compiler starts from and makes
|
The *crate root* is a source file that the Rust compiler starts from and makes
|
||||||
up the root module of your crate (we’ll explain modules in depth in “Defining
|
up the root module of your crate (we’ll explain modules in depth in the
|
||||||
Modules to Control Scope and Privacy” on page XX).
|
“Defining Modules to Control Scope and Privacy”
|
||||||
|
section).
|
||||||
|
|
||||||
A *package* is a bundle of one or more crates that provides a set of
|
A *package* is a bundle of one or more crates that provides a set of
|
||||||
functionality. A package contains a *Cargo.toml* file that describes how to
|
functionality. A package contains a *Cargo.toml* file that describes how to
|
||||||
build those crates. Cargo is actually a package that contains the binary crate
|
build those crates. Cargo is actually a package that contains the binary crate
|
||||||
for the command line tool you’ve been using to build your code. The Cargo
|
for the command-line tool you’ve been using to build your code. The Cargo
|
||||||
package also contains a library crate that the binary crate depends on. Other
|
package also contains a library crate that the binary crate depends on. Other
|
||||||
projects can depend on the Cargo library crate to use the same logic the Cargo
|
projects can depend on the Cargo library crate to use the same logic the Cargo
|
||||||
command line tool uses.
|
command-line tool uses.
|
||||||
|
|
||||||
A crate can come in one of two forms: a binary crate or a library crate. A
|
A crate can come in one of two forms: a binary crate or a library crate. A
|
||||||
package can contain as many binary crates as you like, but at most only one
|
package can contain as many binary crates as you like, but at most only one
|
||||||
|
@ -123,94 +124,6 @@ and *src/lib.rs*, it has two crates: a binary and a library, both with the same
|
||||||
name as the package. A package can have multiple binary crates by placing files
|
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.
|
in the *src/bin* directory: each file will be a separate binary crate.
|
||||||
|
|
||||||
> ### Modules Cheat Sheet
|
|
||||||
>
|
|
||||||
> Before we get to the details of modules and paths, here we provide a quick
|
|
||||||
reference on how modules, paths, the `use` keyword, and the `pub` keyword work
|
|
||||||
in the compiler, and how most developers organize their code. We’ll be going
|
|
||||||
through examples of each of these rules throughout this chapter, but this is a
|
|
||||||
great place to refer to as a reminder of how modules work.
|
|
||||||
>
|
|
||||||
> * **Start from the crate root**: When compiling a crate, the compiler first
|
|
||||||
looks in the crate root file (usually *src/lib.rs* for a library crate or
|
|
||||||
*src/main.rs* for a binary crate) for code to compile.
|
|
||||||
> * **Declaring modules**: In the crate root file, you can declare new modules;
|
|
||||||
say you declare a “garden” module with `mod garden;`. The compiler will look
|
|
||||||
for the module’s code in these places:
|
|
||||||
>
|
|
||||||
> * Inline, within curly brackets that replace the semicolon following `mod
|
|
||||||
garden`
|
|
||||||
> * In the file *src/garden.rs.*
|
|
||||||
> * In the file *src/garden/mod.rs*
|
|
||||||
> * **Declaring submodules**: In any file other than the crate root, you can
|
|
||||||
declare submodules. For example, you might declare `mod vegetables;` in
|
|
||||||
*src/garden.rs*. The compiler will look for the submodule’s code within the
|
|
||||||
directory named for the parent module in these places:
|
|
||||||
>
|
|
||||||
> * Inline, directly following `mod vegetables`, within curly brackets instead
|
|
||||||
of the semicolon
|
|
||||||
> * In the file *src/garden/vegetables.rs*
|
|
||||||
> * In the file *src/garden/vegetables/mod.rs*
|
|
||||||
> * **Paths to code in modules**: Once a module is part of your crate, you can
|
|
||||||
refer to code in that module from anywhere else in that same crate, as long as
|
|
||||||
the privacy rules allow, using the path to the code. For example, an
|
|
||||||
`Asparagus` type in the garden vegetables module would be found at
|
|
||||||
`crate::garden::vegetables::Asparagus`.
|
|
||||||
> * **Private vs. public**: Code within a module is private from its parent
|
|
||||||
modules by default. To make a module public, declare it with `pub mod` instead
|
|
||||||
of `mod`. To make items within a public module public as well, use `pub` before
|
|
||||||
their declarations.
|
|
||||||
> * **The use keyword**: Within a scope, the `use` keyword creates shortcuts to
|
|
||||||
items to reduce repetition of long paths. In any scope that can refer to
|
|
||||||
`crate::garden::vegetables::Asparagus`, you can create a shortcut with `use
|
|
||||||
crate::garden::vegetables::Asparagus;` and from then on you only need to write
|
|
||||||
`Asparagus` to make use of that type in the scope.
|
|
||||||
>
|
|
||||||
> Here, we create a binary crate named `backyard` that illustrates these rules.
|
|
||||||
The crate’s directory, also named `backyard`, contains these files and
|
|
||||||
directories:
|
|
||||||
>
|
|
||||||
> ```
|
|
||||||
> backyard
|
|
||||||
> ├── Cargo.lock
|
|
||||||
> ├── Cargo.toml
|
|
||||||
> └── src
|
|
||||||
> ├── garden
|
|
||||||
> │ └── vegetables.rs
|
|
||||||
> ├── garden.rs
|
|
||||||
> └── main.rs
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> The crate root file in this case is *src/main.rs*, and it contains:
|
|
||||||
>
|
|
||||||
> ```
|
|
||||||
> use crate::garden::vegetables::Asparagus;
|
|
||||||
>
|
|
||||||
> pub mod garden;
|
|
||||||
>
|
|
||||||
> fn main() {
|
|
||||||
> let plant = Asparagus {};
|
|
||||||
> println!("I'm growing {:?}!", plant);
|
|
||||||
> }
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> The `pub mod garden;` line tells the compiler to include the code it finds in
|
|
||||||
*src/garden.rs*, which is:
|
|
||||||
>
|
|
||||||
> ```
|
|
||||||
> pub mod vegetables;
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> Here, `pub mod vegetables;` means the code in *src/garden/vegetables.rs* is
|
|
||||||
included too. That code is:
|
|
||||||
>
|
|
||||||
> ```
|
|
||||||
> #[derive(Debug)]
|
|
||||||
> pub struct Asparagus {}
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> Now let’s get into the details of these rules and demonstrate them in action!
|
|
||||||
|
|
||||||
## Defining Modules to Control Scope and Privacy
|
## Defining Modules to Control Scope and Privacy
|
||||||
|
|
||||||
In this section, we’ll talk about modules and other parts of the module system,
|
In this section, we’ll talk about modules and other parts of the module system,
|
||||||
|
@ -218,6 +131,98 @@ namely *paths*, which allow you to name items; the `use` keyword that brings a
|
||||||
path into scope; and the `pub` keyword to make items public. We’ll also discuss
|
path into scope; and the `pub` keyword to make items public. We’ll also discuss
|
||||||
the `as` keyword, external packages, and the glob operator.
|
the `as` keyword, external packages, and the glob operator.
|
||||||
|
|
||||||
|
### Modules Cheat Sheet
|
||||||
|
|
||||||
|
Before we get to the details of modules and paths, here we provide a quick
|
||||||
|
reference on how modules, paths, the `use` keyword, and the `pub` keyword work
|
||||||
|
in the compiler, and how most developers organize their code. We’ll be going
|
||||||
|
through examples of each of these rules throughout this chapter, but this is a
|
||||||
|
great place to refer to as a reminder of how modules work.
|
||||||
|
|
||||||
|
- **Start from the crate root**: When compiling a crate, the compiler first
|
||||||
|
looks in the crate root file (usually *src/lib.rs* for a library crate or
|
||||||
|
*src/main.rs* for a binary crate) for code to compile.
|
||||||
|
- **Declaring modules**: In the crate root file, you can declare new modules;
|
||||||
|
say you declare a “garden” module with `mod garden;`. The compiler will look
|
||||||
|
for the module’s code in these places:
|
||||||
|
- Inline, within curly brackets that replace the semicolon following `mod
|
||||||
|
garden`
|
||||||
|
- In the file *src/garden.rs*
|
||||||
|
- In the file *src/garden/mod.rs*
|
||||||
|
- **Declaring submodules**: In any file other than the crate root, you can
|
||||||
|
declare submodules. For example, you might declare `mod vegetables;` in
|
||||||
|
*src/garden.rs*. The compiler will look for the submodule’s code within the
|
||||||
|
directory named for the parent module in these places:
|
||||||
|
- Inline, directly following `mod vegetables`, within curly brackets instead
|
||||||
|
of the semicolon
|
||||||
|
- In the file *src/garden/vegetables.rs*
|
||||||
|
- In the file *src/garden/vegetables/mod.rs*
|
||||||
|
- **Paths to code in modules**: Once a module is part of your crate, you can
|
||||||
|
refer to code in that module from anywhere else in that same crate, as long
|
||||||
|
as the privacy rules allow, using the path to the code. For example, an
|
||||||
|
`Asparagus` type in the garden vegetables module would be found at
|
||||||
|
`crate::garden::vegetables::Asparagus`.
|
||||||
|
- **Private vs. public**: Code within a module is private from its parent
|
||||||
|
modules by default. To make a module public, declare it with `pub mod`
|
||||||
|
instead of `mod`. To make items within a public module public as well, use
|
||||||
|
`pub` before their declarations.
|
||||||
|
- **The `use` keyword**: Within a scope, the `use` keyword creates shortcuts to
|
||||||
|
items to reduce repetition of long paths. In any scope that can refer to
|
||||||
|
`crate::garden::vegetables::Asparagus`, you can create a shortcut with `use
|
||||||
|
crate::garden::vegetables::Asparagus;` and from then on you only need to
|
||||||
|
write `Asparagus` to make use of that type in the scope.
|
||||||
|
|
||||||
|
Here, we create a binary crate named `backyard` that illustrates these rules.
|
||||||
|
The crate’s directory, also named `backyard`, contains these files and
|
||||||
|
directories:
|
||||||
|
|
||||||
|
```
|
||||||
|
backyard
|
||||||
|
├── Cargo.lock
|
||||||
|
├── Cargo.toml
|
||||||
|
└── src
|
||||||
|
├── garden
|
||||||
|
│ └── vegetables.rs
|
||||||
|
├── garden.rs
|
||||||
|
└── main.rs
|
||||||
|
```
|
||||||
|
|
||||||
|
The crate root file in this case is *src/main.rs*, and it contains:
|
||||||
|
|
||||||
|
Filename: src/main.rs
|
||||||
|
|
||||||
|
```
|
||||||
|
use crate::garden::vegetables::Asparagus;
|
||||||
|
|
||||||
|
pub mod garden;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let plant = Asparagus {};
|
||||||
|
println!("I'm growing {:?}!", plant);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `pub mod garden;` line tells the compiler to include the code it finds in
|
||||||
|
*src/garden.rs*, which is:
|
||||||
|
|
||||||
|
Filename: src/garden.rs
|
||||||
|
|
||||||
|
```
|
||||||
|
pub mod vegetables;
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, `pub mod vegetables;` means the code in *src/garden/vegetables.rs* is
|
||||||
|
included too. That code is:
|
||||||
|
|
||||||
|
```
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Asparagus {}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now let’s get into the details of these rules and demonstrate them in action!
|
||||||
|
|
||||||
|
### Grouping Related Code in Modules
|
||||||
|
|
||||||
*Modules* let us organize code within a crate for readability and easy reuse.
|
*Modules* let us organize code within a crate for readability and easy reuse.
|
||||||
Modules also allow us to control the *privacy* of items because code within a
|
Modules also allow us to control the *privacy* of items because code within a
|
||||||
module is private by default. Private items are internal implementation details
|
module is private by default. Private items are internal implementation details
|
||||||
|
@ -263,8 +268,8 @@ mod front_of_house {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-1: A `front_of_house` module containing other modules that then
|
Listing 7-1: A `front_of_house` module containing other
|
||||||
contain functions
|
modules that then contain functions
|
||||||
|
|
||||||
We define a module with the `mod` keyword followed by the name of the module
|
We define a module with the `mod` keyword followed by the name of the module
|
||||||
(in this case, `front_of_house`). The body of the module then goes inside curly
|
(in this case, `front_of_house`). The body of the module then goes inside curly
|
||||||
|
@ -298,7 +303,8 @@ crate
|
||||||
└── take_payment
|
└── take_payment
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-2: The module tree for the code in Listing 7-1
|
Listing 7-2: The module tree for the code in Listing
|
||||||
|
7-1
|
||||||
|
|
||||||
This tree shows how some of the modules nest inside other modules; for example,
|
This tree shows how some of the modules nest inside other modules; for example,
|
||||||
`hosting` nests inside `front_of_house`. The tree also shows that some modules
|
`hosting` nests inside `front_of_house`. The tree also shows that some modules
|
||||||
|
@ -321,18 +327,19 @@ know its path.
|
||||||
|
|
||||||
A path can take two forms:
|
A path can take two forms:
|
||||||
|
|
||||||
* An *absolute path* is the full path starting from a crate root; for code from
|
* An *absolute path* is the full path starting from a crate root; for code
|
||||||
an external crate, the absolute path begins with the crate name, and for code
|
from an external crate, the absolute path begins with the crate name, and for
|
||||||
from the current crate, it starts with the literal `crate`.
|
code from the current crate, it starts with the literal `crate`.
|
||||||
* A *relative path* starts from the current module and uses `self`, `super`, or
|
* A *relative path* starts from the current module and uses `self`, `super`, or
|
||||||
an identifier in the current module.
|
an identifier in the current module.
|
||||||
|
|
||||||
Both absolute and relative paths are followed by one or more identifiers
|
Both absolute and relative paths are followed by one or more identifiers
|
||||||
separated by double colons (`::`).
|
separated by double colons (`::`).
|
||||||
|
|
||||||
Returning to Listing 7-1, say we want to call the `add_to_waitlist` function.
|
Returning to Listing 7-1, say we want to call the `add_to_waitlist` function.
|
||||||
This is the same as asking: what’s the path of the `add_to_waitlist` function?
|
This is the same as asking: what’s the path of the `add_to_waitlist` function?
|
||||||
Listing 7-3 contains Listing 7-1 with some of the modules and functions removed.
|
Listing 7-3 contains Listing 7-1 with some of the modules and functions
|
||||||
|
removed.
|
||||||
|
|
||||||
We’ll show two ways to call the `add_to_waitlist` function from a new function,
|
We’ll show two ways to call the `add_to_waitlist` function from a new function,
|
||||||
`eat_at_restaurant`, defined in the crate root. These paths are correct, but
|
`eat_at_restaurant`, defined in the crate root. These paths are correct, but
|
||||||
|
@ -340,8 +347,8 @@ there’s another problem remaining that will prevent this example from compilin
|
||||||
as is. We’ll explain why in a bit.
|
as is. We’ll explain why in a bit.
|
||||||
|
|
||||||
The `eat_at_restaurant` function is part of our library crate’s public API, so
|
The `eat_at_restaurant` function is part of our library crate’s public API, so
|
||||||
we mark it with the `pub` keyword. In “Exposing Paths with the pub Keyword” on
|
we mark it with the `pub` keyword. In the “Exposing Paths with the `pub`
|
||||||
page XX, we’ll go into more detail about `pub`.
|
Keyword” section, we’ll go into more detail about `pub`.
|
||||||
|
|
||||||
Filename: src/lib.rs
|
Filename: src/lib.rs
|
||||||
|
|
||||||
|
@ -361,8 +368,8 @@ pub fn eat_at_restaurant() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-3: Calling the `add_to_waitlist` function using absolute and relative
|
Listing 7-3: Calling the `add_to_waitlist` function using
|
||||||
paths
|
absolute and relative paths
|
||||||
|
|
||||||
The first time we call the `add_to_waitlist` function in `eat_at_restaurant`,
|
The first time we call the `add_to_waitlist` function in `eat_at_restaurant`,
|
||||||
we use an absolute path. The `add_to_waitlist` function is defined in the same
|
we use an absolute path. The `add_to_waitlist` function is defined in the same
|
||||||
|
@ -403,7 +410,9 @@ error[E0603]: module `hosting` is private
|
||||||
--> src/lib.rs:9:28
|
--> src/lib.rs:9:28
|
||||||
|
|
|
|
||||||
9 | crate::front_of_house::hosting::add_to_waitlist();
|
9 | crate::front_of_house::hosting::add_to_waitlist();
|
||||||
| ^^^^^^^ private module
|
| ^^^^^^^ --------------- function `add_to_waitlist` is not publicly re-exported
|
||||||
|
| |
|
||||||
|
| private module
|
||||||
|
|
|
|
||||||
note: the module `hosting` is defined here
|
note: the module `hosting` is defined here
|
||||||
--> src/lib.rs:2:5
|
--> src/lib.rs:2:5
|
||||||
|
@ -415,16 +424,22 @@ error[E0603]: module `hosting` is private
|
||||||
--> src/lib.rs:12:21
|
--> src/lib.rs:12:21
|
||||||
|
|
|
|
||||||
12 | front_of_house::hosting::add_to_waitlist();
|
12 | front_of_house::hosting::add_to_waitlist();
|
||||||
| ^^^^^^^ private module
|
| ^^^^^^^ --------------- function `add_to_waitlist` is not publicly re-exported
|
||||||
|
| |
|
||||||
|
| private module
|
||||||
|
|
|
|
||||||
note: the module `hosting` is defined here
|
note: the module `hosting` is defined here
|
||||||
--> src/lib.rs:2:5
|
--> src/lib.rs:2:5
|
||||||
|
|
|
|
||||||
2 | mod hosting {
|
2 | mod hosting {
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0603`.
|
||||||
|
error: could not compile `restaurant` (lib) due to 2 previous errors
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-4: Compiler errors from building the code in Listing 7-3
|
Listing 7-4: Compiler errors from building the code in
|
||||||
|
Listing 7-3
|
||||||
|
|
||||||
The error messages say that module `hosting` is private. In other words, we
|
The error messages say that module `hosting` is private. In other words, we
|
||||||
have the correct paths for the `hosting` module and the `add_to_waitlist`
|
have the correct paths for the `hosting` module and the `add_to_waitlist`
|
||||||
|
@ -447,7 +462,7 @@ inner code you can change without breaking outer code. However, Rust does give
|
||||||
you the option to expose inner parts of child modules’ code to outer ancestor
|
you the option to expose inner parts of child modules’ code to outer ancestor
|
||||||
modules by using the `pub` keyword to make an item public.
|
modules by using the `pub` keyword to make an item public.
|
||||||
|
|
||||||
### Exposing Paths with the pub Keyword
|
### Exposing Paths with the `pub` Keyword
|
||||||
|
|
||||||
Let’s return to the error in Listing 7-4 that told us the `hosting` module is
|
Let’s 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
|
private. We want the `eat_at_restaurant` function in the parent module to have
|
||||||
|
@ -463,11 +478,17 @@ mod front_of_house {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
--snip--
|
pub fn eat_at_restaurant() {
|
||||||
|
// Absolute path
|
||||||
|
crate::front_of_house::hosting::add_to_waitlist();
|
||||||
|
|
||||||
|
// Relative path
|
||||||
|
front_of_house::hosting::add_to_waitlist();
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-5: Declaring the `hosting` module as `pub` to use it from
|
Listing 7-5: Declaring the `hosting` module as `pub` to
|
||||||
`eat_at_restaurant`
|
use it from `eat_at_restaurant`
|
||||||
|
|
||||||
Unfortunately, the code in Listing 7-5 still results in compiler errors, as
|
Unfortunately, the code in Listing 7-5 still results in compiler errors, as
|
||||||
shown in Listing 7-6.
|
shown in Listing 7-6.
|
||||||
|
@ -498,9 +519,13 @@ note: the function `add_to_waitlist` is defined here
|
||||||
|
|
|
|
||||||
3 | fn add_to_waitlist() {}
|
3 | fn add_to_waitlist() {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0603`.
|
||||||
|
error: could not compile `restaurant` (lib) due to 2 previous errors
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-6: Compiler errors from building the code in Listing 7-5
|
Listing 7-6: Compiler errors from building the code in
|
||||||
|
Listing 7-5
|
||||||
|
|
||||||
What happened? Adding the `pub` keyword in front of `mod hosting` makes the
|
What happened? Adding the `pub` keyword in front of `mod hosting` makes the
|
||||||
module public. With this change, if we can access `front_of_house`, we can
|
module public. With this change, if we can access `front_of_house`, we can
|
||||||
|
@ -527,11 +552,18 @@ mod front_of_house {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
--snip--
|
pub fn eat_at_restaurant() {
|
||||||
|
// Absolute path
|
||||||
|
crate::front_of_house::hosting::add_to_waitlist();
|
||||||
|
|
||||||
|
// Relative path
|
||||||
|
front_of_house::hosting::add_to_waitlist();
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-7: Adding the `pub` keyword to `mod hosting` and `fn add_to_waitlist`
|
Listing 7-7: Adding the `pub` keyword to `mod hosting`
|
||||||
lets us call the function from `eat_at_restaurant`.
|
and `fn add_to_waitlist` lets us call the function from
|
||||||
|
`eat_at_restaurant`
|
||||||
|
|
||||||
Now the code will compile! To see why adding the `pub` keyword lets us use
|
Now the code will compile! To see why adding the `pub` keyword lets us use
|
||||||
these paths in `add_to_waitlist` with respect to the privacy rules, let’s look
|
these paths in `add_to_waitlist` with respect to the privacy rules, let’s look
|
||||||
|
@ -559,31 +591,31 @@ If you plan on sharing your library crate so other projects can use your code,
|
||||||
your public API is your contract with users of your crate that determines how
|
your public API is your contract with users of your crate that determines how
|
||||||
they can interact with your code. There are many considerations around managing
|
they can interact with your code. There are many considerations around managing
|
||||||
changes to your public API to make it easier for people to depend on your
|
changes to your public API to make it easier for people to depend on your
|
||||||
crate. These considerations are beyond the scope of this book; if you’re
|
crate. These considerations are out of the scope of this book; if you’re
|
||||||
interested in this topic, see the Rust API Guidelines at
|
interested in this topic, see The Rust API Guidelines at *https://rust-lang.github.io/api-guidelines/*.
|
||||||
*https://rust-lang.github.io/api-guidelines*.
|
|
||||||
|
|
||||||
> ### Best Practices for Packages with a Binary and a Library
|
> #### Best Practices for Packages with a Binary and a Library
|
||||||
>
|
>
|
||||||
> We mentioned that a package can contain both a *src/main.rs* binary crate
|
> We mentioned that a package can contain both a *src/main.rs* binary crate
|
||||||
root as well as a *src/lib.rs* library crate root, and both crates will have
|
> root as well as a *src/lib.rs* library crate root, and both crates will have
|
||||||
the package name by default. Typically, packages with this pattern of
|
> the package name by default. Typically, packages with this pattern of
|
||||||
containing both a library and a binary crate will have just enough code in the
|
> containing both a library and a binary crate will have just enough code in the
|
||||||
binary crate to start an executable that calls code with the library crate.
|
> binary crate to start an executable that calls code within the library crate.
|
||||||
This lets other projects benefit from the most functionality that the package
|
> This lets other projects benefit from most of the functionality that the
|
||||||
provides because the library crate’s code can be shared.
|
> package provides because the library crate’s code can be shared.
|
||||||
>
|
>
|
||||||
> The module tree should be defined in *src/lib.rs*. Then, any public items can
|
> The module tree should be defined in *src/lib.rs*. Then, any public items can
|
||||||
be used in the binary crate by starting paths with the name of the package. The
|
> be used in the binary crate by starting paths with the name of the package.
|
||||||
binary crate becomes a user of the library crate just like a completely
|
> The binary crate becomes a user of the library crate just like a completely
|
||||||
external crate would use the library crate: it can only use the public API.
|
> external crate would use the library crate: it can only use the public API.
|
||||||
This helps you design a good API; not only are you the author, you’re also a
|
> This helps you design a good API; not only are you the author, you’re also a
|
||||||
client!
|
> client!
|
||||||
>
|
>
|
||||||
> In Chapter 12, we’ll demonstrate this organizational practice with a command
|
> In Chapter 12, we’ll demonstrate this organizational
|
||||||
line program that will contain both a binary crate and a library crate.
|
> practice with a command-line program that will contain both a binary crate
|
||||||
|
> and a library crate.
|
||||||
|
|
||||||
### Starting Relative Paths with super
|
### Starting Relative Paths with `super`
|
||||||
|
|
||||||
We can construct relative paths that begin in the parent module, rather than
|
We can construct relative paths that begin in the parent module, rather than
|
||||||
the current module or the crate root, by using `super` at the start of the
|
the current module or the crate root, by using `super` at the start of the
|
||||||
|
@ -614,7 +646,8 @@ mod back_of_house {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-8: Calling a function using a relative path starting with `super`
|
Listing 7-8: Calling a function using a relative path
|
||||||
|
starting with `super`
|
||||||
|
|
||||||
The `fix_incorrect_order` function is in the `back_of_house` module, so we can
|
The `fix_incorrect_order` function is in the `back_of_house` module, so we can
|
||||||
use `super` to go to the parent module of `back_of_house`, which in this case
|
use `super` to go to the parent module of `back_of_house`, which in this case
|
||||||
|
@ -664,14 +697,14 @@ pub fn eat_at_restaurant() {
|
||||||
meal.toast = String::from("Wheat");
|
meal.toast = String::from("Wheat");
|
||||||
println!("I'd like {} toast please", meal.toast);
|
println!("I'd like {} toast please", meal.toast);
|
||||||
|
|
||||||
// The next line won't compile if we uncomment it; we're not
|
// The next line won't compile if we uncomment it; we're not allowed
|
||||||
// allowed to see or modify the seasonal fruit that comes
|
// to see or modify the seasonal fruit that comes with the meal
|
||||||
// with the meal
|
|
||||||
// meal.seasonal_fruit = String::from("blueberries");
|
// meal.seasonal_fruit = String::from("blueberries");
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-9: A struct with some public fields and some private fields
|
Listing 7-9: A struct with some public fields and some
|
||||||
|
private fields
|
||||||
|
|
||||||
Because the `toast` field in 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
|
in `eat_at_restaurant` we can write and read to the `toast` field using dot
|
||||||
|
@ -705,7 +738,8 @@ pub fn eat_at_restaurant() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-10: Designating an enum as public makes all its variants public.
|
Listing 7-10: Designating an enum as public makes all its
|
||||||
|
variants public
|
||||||
|
|
||||||
Because we made the `Appetizer` enum public, we can use the `Soup` and `Salad`
|
Because we made the `Appetizer` enum public, we can use the `Soup` and `Salad`
|
||||||
variants in `eat_at_restaurant`.
|
variants in `eat_at_restaurant`.
|
||||||
|
@ -720,7 +754,7 @@ There’s one more situation involving `pub` that we haven’t covered, and that
|
||||||
our last module system feature: the `use` keyword. We’ll cover `use` by itself
|
our last module system feature: the `use` keyword. We’ll cover `use` by itself
|
||||||
first, and then we’ll show how to combine `pub` and `use`.
|
first, and then we’ll show how to combine `pub` and `use`.
|
||||||
|
|
||||||
## Bringing Paths into Scope with the use Keyword
|
## Bringing Paths into Scope with the `use` Keyword
|
||||||
|
|
||||||
Having to write out the paths to call functions can feel inconvenient and
|
Having to write out the paths to call functions can feel inconvenient and
|
||||||
repetitive. In Listing 7-7, whether we chose the absolute or relative path to
|
repetitive. In Listing 7-7, whether we chose the absolute or relative path to
|
||||||
|
@ -750,7 +784,8 @@ pub fn eat_at_restaurant() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-11: Bringing a module into scope with `use`
|
Listing 7-11: Bringing a module into scope with
|
||||||
|
`use`
|
||||||
|
|
||||||
Adding `use` and a path in a scope is similar to creating a symbolic link in
|
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
|
the filesystem. By adding `use crate::front_of_house::hosting` in the crate
|
||||||
|
@ -781,17 +816,25 @@ mod customer {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-12: A `use` statement only applies in the scope it’s in.
|
Listing 7-12: A `use` statement only applies in the scope
|
||||||
|
it’s in
|
||||||
|
|
||||||
The compiler error shows that the shortcut no longer applies within the
|
The compiler error shows that the shortcut no longer applies within the
|
||||||
`customer` module:
|
`customer` module:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
$ cargo build
|
||||||
|
Compiling restaurant v0.1.0 (file:///projects/restaurant)
|
||||||
error[E0433]: failed to resolve: use of undeclared crate or module `hosting`
|
error[E0433]: failed to resolve: use of undeclared crate or module `hosting`
|
||||||
--> src/lib.rs:11:9
|
--> src/lib.rs:11:9
|
||||||
|
|
|
|
||||||
11 | hosting::add_to_waitlist();
|
11 | hosting::add_to_waitlist();
|
||||||
| ^^^^^^^ use of undeclared crate or module `hosting`
|
| ^^^^^^^ use of undeclared crate or module `hosting`
|
||||||
|
|
|
||||||
|
help: consider importing this module through its public re-export
|
||||||
|
|
|
||||||
|
10 + use crate::hosting;
|
||||||
|
|
|
||||||
|
|
||||||
warning: unused import: `crate::front_of_house::hosting`
|
warning: unused import: `crate::front_of_house::hosting`
|
||||||
--> src/lib.rs:7:5
|
--> src/lib.rs:7:5
|
||||||
|
@ -800,6 +843,10 @@ warning: unused import: `crate::front_of_house::hosting`
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `#[warn(unused_imports)]` on by default
|
= note: `#[warn(unused_imports)]` on by default
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0433`.
|
||||||
|
warning: `restaurant` (lib) generated 1 warning
|
||||||
|
error: could not compile `restaurant` (lib) due to 1 previous error; 1 warning emitted
|
||||||
```
|
```
|
||||||
|
|
||||||
Notice there’s also a warning that the `use` is no longer used in its scope! To
|
Notice there’s also a warning that the `use` is no longer used in its scope! To
|
||||||
|
@ -807,7 +854,7 @@ fix this problem, move the `use` within the `customer` module too, or reference
|
||||||
the shortcut in the parent module with `super::hosting` within the child
|
the shortcut in the parent module with `super::hosting` within the child
|
||||||
`customer` module.
|
`customer` module.
|
||||||
|
|
||||||
### Creating Idiomatic use Paths
|
### Creating Idiomatic `use` Paths
|
||||||
|
|
||||||
In Listing 7-11, you might 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
|
crate::front_of_house::hosting` and then called `hosting::add_to_waitlist` in
|
||||||
|
@ -830,8 +877,8 @@ pub fn eat_at_restaurant() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-13: Bringing the `add_to_waitlist` function into scope with `use`,
|
Listing 7-13: Bringing the `add_to_waitlist` function
|
||||||
which is unidiomatic
|
into scope with `use`, which is unidiomatic
|
||||||
|
|
||||||
Although both Listing 7-11 and Listing 7-13 accomplish the same task, Listing
|
Although both Listing 7-11 and Listing 7-13 accomplish the same task, Listing
|
||||||
7-11 is the idiomatic way to bring a function into scope with `use`. Bringing
|
7-11 is the idiomatic way to bring a function into scope with `use`. Bringing
|
||||||
|
@ -857,7 +904,8 @@ fn main() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-14: Bringing `HashMap` into scope in an idiomatic way
|
Listing 7-14: Bringing `HashMap` into scope in an
|
||||||
|
idiomatic way
|
||||||
|
|
||||||
There’s no strong reason behind this idiom: it’s just the convention that has
|
There’s no strong reason behind this idiom: it’s just the convention that has
|
||||||
emerged, and folks have gotten used to reading and writing Rust code this way.
|
emerged, and folks have gotten used to reading and writing Rust code this way.
|
||||||
|
@ -874,23 +922,23 @@ use std::fmt;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
fn function1() -> fmt::Result {
|
fn function1() -> fmt::Result {
|
||||||
--snip--
|
// --snip--
|
||||||
}
|
}
|
||||||
|
|
||||||
fn function2() -> io::Result<()> {
|
fn function2() -> io::Result<()> {
|
||||||
--snip--
|
// --snip--
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-15: Bringing two types with the same name into the same scope
|
Listing 7-15: Bringing two types with the same name into
|
||||||
requires using their parent modules.
|
the same scope requires using their parent modules.
|
||||||
|
|
||||||
As you can see, using the parent modules distinguishes the two `Result` types.
|
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`, we’d
|
If instead we specified `use std::fmt::Result` and `use std::io::Result`, we’d
|
||||||
have two `Result` types in the same scope, and Rust wouldn’t know which one we
|
have two `Result` types in the same scope, and Rust wouldn’t know which one we
|
||||||
meant when we used `Result`.
|
meant when we used `Result`.
|
||||||
|
|
||||||
### Providing New Names with the as Keyword
|
### Providing New Names with the `as` Keyword
|
||||||
|
|
||||||
There’s another solution to the problem of bringing two types of the same name
|
There’s 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
|
into the same scope with `use`: after the path, we can specify `as` and a new
|
||||||
|
@ -904,22 +952,23 @@ use std::fmt::Result;
|
||||||
use std::io::Result as IoResult;
|
use std::io::Result as IoResult;
|
||||||
|
|
||||||
fn function1() -> Result {
|
fn function1() -> Result {
|
||||||
--snip--
|
// --snip--
|
||||||
}
|
}
|
||||||
|
|
||||||
fn function2() -> IoResult<()> {
|
fn function2() -> IoResult<()> {
|
||||||
--snip--
|
// --snip--
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-16: Renaming a type when it’s brought into scope with the `as` keyword
|
Listing 7-16: Renaming a type when it’s brought into
|
||||||
|
scope with the `as` keyword
|
||||||
|
|
||||||
In the second `use` statement, we chose the new name `IoResult` for the
|
In the second `use` statement, we chose the new name `IoResult` for the
|
||||||
`std::io::Result` type, which won’t conflict with the `Result` from `std::fmt`
|
`std::io::Result` type, which won’t conflict with the `Result` from `std::fmt`
|
||||||
that we’ve also brought into scope. Listing 7-15 and Listing 7-16 are
|
that we’ve also brought into scope. Listing 7-15 and Listing 7-16 are
|
||||||
considered idiomatic, so the choice is up to you!
|
considered idiomatic, so the choice is up to you!
|
||||||
|
|
||||||
### Re-exporting Names with pub use
|
### Re-exporting Names with `pub use`
|
||||||
|
|
||||||
When we bring a name into scope with the `use` keyword, the name available in
|
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
|
the new scope is private. To enable the code that calls our code to refer to
|
||||||
|
@ -947,12 +996,13 @@ pub fn eat_at_restaurant() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-17: Making a name available for any code to use from a new scope with
|
Listing 7-17: Making a name available for any code to use
|
||||||
`pub use`
|
from a new scope with `pub use`
|
||||||
|
|
||||||
Before this change, external code would have to call the `add_to_waitlist`
|
Before this change, external code would have to call the `add_to_waitlist`
|
||||||
function by using the path
|
function by using the path
|
||||||
`restaurant::front_of_house::hosting::add_to_waitlist()`. Now that this `pub
|
`restaurant::front_of_house::hosting::add_to_waitlist()`, which also would have
|
||||||
|
required the `front_of_house` module to be marked as `pub`. Now that this `pub
|
||||||
use` has re-exported the `hosting` module from the root module, external code
|
use` has re-exported the `hosting` module from the root module, external code
|
||||||
can use the path `restaurant::hosting::add_to_waitlist()` instead.
|
can use the path `restaurant::hosting::add_to_waitlist()` instead.
|
||||||
|
|
||||||
|
@ -964,8 +1014,9 @@ probably won’t 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
|
`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
|
structure. Doing so makes our library well organized for programmers working on
|
||||||
the library and programmers calling the library. We’ll look at another example
|
the library and programmers calling the library. We’ll look at another example
|
||||||
of `pub use` and how it affects your crate’s documentation in “Exporting a
|
of `pub use` and how it affects your crate’s documentation in the “Exporting a
|
||||||
Convenient Public API with pub use” on page XX.
|
Convenient Public API with `pub use`” section of
|
||||||
|
Chapter 14.
|
||||||
|
|
||||||
### Using External Packages
|
### Using External Packages
|
||||||
|
|
||||||
|
@ -973,6 +1024,12 @@ 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
|
package called `rand` to get random numbers. To use `rand` in our project, we
|
||||||
added this line to *Cargo.toml*:
|
added this line to *Cargo.toml*:
|
||||||
|
|
||||||
|
<!-- When updating the version of `rand` used, also update the version of
|
||||||
|
`rand` used in these files so they all match:
|
||||||
|
* ch02-00-guessing-game-tutorial.md
|
||||||
|
* ch14-03-cargo-workspaces.md
|
||||||
|
-->
|
||||||
|
|
||||||
Filename: Cargo.toml
|
Filename: Cargo.toml
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -980,14 +1037,14 @@ rand = "0.8.5"
|
||||||
```
|
```
|
||||||
|
|
||||||
Adding `rand` as a dependency in *Cargo.toml* tells Cargo to download the
|
Adding `rand` as a dependency in *Cargo.toml* tells Cargo to download the
|
||||||
`rand` package and any dependencies from *https://crates.io*, and make `rand`
|
`rand` package and any dependencies from crates.io at *https://crates.io/* and
|
||||||
available to our project.
|
make `rand` available to our project.
|
||||||
|
|
||||||
Then, to bring `rand` definitions into the scope of our package, we added a
|
Then, to bring `rand` definitions into the scope of our package, we added a
|
||||||
`use` line starting with the name of the crate, `rand`, and listed the items we
|
`use` line starting with the name of the crate, `rand`, and listed the items
|
||||||
wanted to bring into scope. Recall that in “Generating a Random Number” on page
|
we wanted to bring into scope. Recall that in the “Generating a Random
|
||||||
XX, we brought the `Rng` trait into scope and called the `rand::thread_rng`
|
Number” section in Chapter 2, we brought the `Rng` trait
|
||||||
function:
|
into scope and called the `rand::thread_rng` function:
|
||||||
|
|
||||||
```
|
```
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
@ -998,9 +1055,9 @@ fn main() {
|
||||||
```
|
```
|
||||||
|
|
||||||
Members of the Rust community have made many packages available at
|
Members of the Rust community have made many packages available at
|
||||||
*https://crates.io*, and pulling any of them into your package involves these
|
crates.io at *https://crates.io/*, and pulling any of them into your package
|
||||||
same steps: listing them in your package’s *Cargo.toml* file and using `use` to
|
involves these same steps: listing them in your package’s *Cargo.toml* file and
|
||||||
bring items from their crates into scope.
|
using `use` to bring items from their crates into scope.
|
||||||
|
|
||||||
Note that the standard `std` library is also a crate that’s external to our
|
Note that the standard `std` library is also a crate that’s external to our
|
||||||
package. Because the standard library is shipped with the Rust language, we
|
package. Because the standard library is shipped with the Rust language, we
|
||||||
|
@ -1015,7 +1072,7 @@ use std::collections::HashMap;
|
||||||
This is an absolute path starting with `std`, the name of the standard library
|
This is an absolute path starting with `std`, the name of the standard library
|
||||||
crate.
|
crate.
|
||||||
|
|
||||||
### Using Nested Paths to Clean Up Large use Lists
|
### Using Nested Paths to Clean Up Large `use` Lists
|
||||||
|
|
||||||
If we’re using multiple items defined in the same crate or same module, listing
|
If we’re using multiple items defined in the same crate or same module, listing
|
||||||
each item on its own line can take up a lot of vertical space in our files. For
|
each item on its own line can take up a lot of vertical space in our files. For
|
||||||
|
@ -1025,10 +1082,10 @@ bring items from `std` into scope:
|
||||||
Filename: src/main.rs
|
Filename: src/main.rs
|
||||||
|
|
||||||
```
|
```
|
||||||
--snip--
|
// --snip--
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::io;
|
use std::io;
|
||||||
--snip--
|
// --snip--
|
||||||
```
|
```
|
||||||
|
|
||||||
Instead, we can use nested paths to bring the same items into scope in one
|
Instead, we can use nested paths to bring the same items into scope in one
|
||||||
|
@ -1039,13 +1096,13 @@ differ, as shown in Listing 7-18.
|
||||||
Filename: src/main.rs
|
Filename: src/main.rs
|
||||||
|
|
||||||
```
|
```
|
||||||
--snip--
|
// --snip--
|
||||||
use std::{cmp::Ordering, io};
|
use std::{cmp::Ordering, io};
|
||||||
--snip--
|
// --snip--
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-18: Specifying a nested path to bring multiple items with the same
|
Listing 7-18: Specifying a nested path to bring multiple
|
||||||
prefix into scope
|
items with the same prefix into scope
|
||||||
|
|
||||||
In bigger programs, bringing many items into scope from the same crate or
|
In bigger programs, bringing many items into scope from the same crate or
|
||||||
module using nested paths can reduce the number of separate `use` statements
|
module using nested paths can reduce the number of separate `use` statements
|
||||||
|
@ -1063,7 +1120,8 @@ use std::io;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-19: Two `use` statements where one is a subpath of the other
|
Listing 7-19: Two `use` statements where one is a subpath
|
||||||
|
of the other
|
||||||
|
|
||||||
The common part of these two paths is `std::io`, and that’s the complete first
|
The common part of these two paths is `std::io`, and that’s the complete first
|
||||||
path. To merge these two paths into one `use` statement, we can use `self` in
|
path. To merge these two paths into one `use` statement, we can use `self` in
|
||||||
|
@ -1075,7 +1133,8 @@ Filename: src/lib.rs
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-20: Combining the paths in Listing 7-19 into one `use` statement
|
Listing 7-20: Combining the paths in Listing 7-19 into
|
||||||
|
one `use` statement
|
||||||
|
|
||||||
This line brings `std::io` and `std::io::Write` into scope.
|
This line brings `std::io` and `std::io::Write` into scope.
|
||||||
|
|
||||||
|
@ -1094,9 +1153,11 @@ harder to tell what names are in scope and where a name used in your program
|
||||||
was defined.
|
was defined.
|
||||||
|
|
||||||
The glob operator is often used when testing to bring everything under test
|
The glob operator is often used when testing to bring everything under test
|
||||||
into the `tests` module; we’ll talk about that in “How to Write Tests” on page
|
into the `tests` module; we’ll talk about that in the “How to Write
|
||||||
XX. The glob operator is also sometimes used as part of the prelude pattern:
|
Tests” section in Chapter 11. The glob operator
|
||||||
see the standard library documentation for more information on that pattern.
|
is also sometimes used as part of the prelude pattern: see the standard
|
||||||
|
library documentation
|
||||||
|
for more information on that pattern.
|
||||||
|
|
||||||
## Separating Modules into Different Files
|
## Separating Modules into Different Files
|
||||||
|
|
||||||
|
@ -1128,8 +1189,8 @@ pub fn eat_at_restaurant() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-21: Declaring the `front_of_house` module whose body will be in
|
Listing 7-21: Declaring the `front_of_house` module whose
|
||||||
*src/front_of_house.rs*
|
body will be in *src/front_of_house.rs*
|
||||||
|
|
||||||
Next, place the code that was in the curly brackets into a new file named
|
Next, place the code that was in the curly brackets into a new file named
|
||||||
*src/front_of_house.rs*, as shown in Listing 7-22. The compiler knows to look
|
*src/front_of_house.rs*, as shown in Listing 7-22. The compiler knows to look
|
||||||
|
@ -1144,16 +1205,17 @@ pub mod hosting {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Listing 7-22: Definitions inside the `front_of_house` module in
|
Listing 7-22: Definitions inside the `front_of_house`
|
||||||
*src/front_of_house.rs*
|
module in *src/front_of_house.rs*
|
||||||
|
|
||||||
Note that you only need to load a file using a `mod` declaration *once* in your
|
Note that you only need to load a file using a `mod` declaration *once* in your
|
||||||
module tree. Once the compiler knows the file is part of the project (and knows
|
module tree. Once the compiler knows the file is part of the project (and knows
|
||||||
where in the module tree the code resides because of where you’ve put the `mod`
|
where in the module tree the code resides because of where you’ve put the `mod`
|
||||||
statement), other files in your project should refer to the loaded file’s code
|
statement), other files in your project should refer to the loaded file’s code
|
||||||
using a path to where it was declared, as covered in “Paths for Referring to an
|
using a path to where it was declared, as covered in the “Paths for Referring
|
||||||
Item in the Module Tree” on page XX. In other words, `mod` is *not* an
|
to an Item in the Module Tree” section. In other words,
|
||||||
“include” operation that you may have seen in other programming languages.
|
`mod` is *not* an “include” operation that you may have seen in other
|
||||||
|
programming languages.
|
||||||
|
|
||||||
Next, we’ll extract the `hosting` module to its own file. The process is a bit
|
Next, we’ll extract the `hosting` module to its own file. The process is a bit
|
||||||
different because `hosting` is a child module of `front_of_house`, not of the
|
different because `hosting` is a child module of `front_of_house`, not of the
|
||||||
|
@ -1187,26 +1249,26 @@ directories and files more closely match the module tree.
|
||||||
> ### Alternate File Paths
|
> ### Alternate File Paths
|
||||||
>
|
>
|
||||||
> So far we’ve covered the most idiomatic file paths the Rust compiler uses,
|
> So far we’ve covered the most idiomatic file paths the Rust compiler uses,
|
||||||
but Rust also supports an older style of file path. For a module named
|
> but Rust also supports an older style of file path. For a module named
|
||||||
`front_of_house` declared in the crate root, the compiler will look for the
|
> `front_of_house` declared in the crate root, the compiler will look for the
|
||||||
module’s code in:
|
> module’s code in:
|
||||||
>
|
>
|
||||||
> * *src/front_of_house.rs* (what we covered)
|
> * *src/front_of_house.rs* (what we covered)
|
||||||
> * *src/front_of_house/mod.rs* (older style, still supported path)
|
> * *src/front_of_house/mod.rs* (older style, still supported path)
|
||||||
>
|
>
|
||||||
> For a module named `hosting` that is a submodule of `front_of_house`, the
|
> For a module named `hosting` that is a submodule of `front_of_house`, the
|
||||||
compiler will look for the module’s code in:
|
> compiler will look for the module’s code in:
|
||||||
>
|
>
|
||||||
> * *src/front_of_house/hosting.rs* (what we covered)
|
> * *src/front_of_house/hosting.rs* (what we covered)
|
||||||
> * *src/front_of_house/hosting/mod.rs* (older style, still supported path)
|
> * *src/front_of_house/hosting/mod.rs* (older style, still supported path)
|
||||||
>
|
>
|
||||||
> If you use both styles for the same module, you’ll get a compiler error.
|
> If you use both styles for the same module, you’ll get a compiler error.
|
||||||
Using a mix of both styles for different modules in the same project is
|
> Using a mix of both styles for different modules in the same project is
|
||||||
allowed, but might be confusing for people navigating your project.
|
> allowed, but might be confusing for people navigating your project.
|
||||||
>
|
>
|
||||||
> The main downside to the style that uses files named *mod.rs* is that your
|
> The main downside to the style that uses files named *mod.rs* is that your
|
||||||
project can end up with many files named *mod.rs*, which can get confusing when
|
> project can end up with many files named *mod.rs*, which can get confusing
|
||||||
you have them open in your editor at the same time.
|
> when you have them open in your editor at the same time.
|
||||||
|
|
||||||
We’ve moved each module’s code to a separate file, and the module tree remains
|
We’ve moved each module’s code to a separate file, and the module tree remains
|
||||||
the same. The function calls in `eat_at_restaurant` will work without any
|
the same. The function calls in `eat_at_restaurant` will work without any
|
||||||
|
@ -1230,4 +1292,3 @@ definitions public by adding the `pub` keyword.
|
||||||
|
|
||||||
In the next chapter, we’ll look at some collection data structures in the
|
In the next chapter, we’ll look at some collection data structures in the
|
||||||
standard library that you can use in your neatly organized code.
|
standard library that you can use in your neatly organized code.
|
||||||
|
|
||||||
|
|
|
@ -35,12 +35,13 @@ package also contains a library crate that the binary crate depends on. Other
|
||||||
projects can depend on the Cargo library crate to use the same logic the Cargo
|
projects can depend on the Cargo library crate to use the same logic the Cargo
|
||||||
command-line tool uses.
|
command-line tool uses.
|
||||||
|
|
||||||
A package can contain as many binary crates as you like, but at most only one
|
A crate can come in one of two forms: a binary crate or a library crate. A
|
||||||
|
package can contain as many binary crates as you like, but at most only one
|
||||||
library crate. A package must contain at least one crate, whether that’s a
|
library crate. A package must contain at least one crate, whether that’s a
|
||||||
library or binary crate.
|
library or binary crate.
|
||||||
|
|
||||||
Let’s walk through what happens when we create a package. First, we enter the
|
Let’s walk through what happens when we create a package. First we enter the
|
||||||
command `cargo new`:
|
command `cargo new my-project`:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ cargo new my-project
|
$ cargo new my-project
|
||||||
|
@ -52,15 +53,15 @@ $ ls my-project/src
|
||||||
main.rs
|
main.rs
|
||||||
```
|
```
|
||||||
|
|
||||||
After we run `cargo new`, we use `ls` to see what Cargo creates. In the project
|
After we run `cargo new my-project`, we use `ls` to see what Cargo creates. In
|
||||||
directory, there’s a *Cargo.toml* file, giving us a package. There’s also a
|
the project directory, there’s a *Cargo.toml* file, giving us a package.
|
||||||
*src* directory that contains *main.rs*. Open *Cargo.toml* in your text editor,
|
There’s also a *src* directory that contains *main.rs*. Open *Cargo.toml* in
|
||||||
and note there’s no mention of *src/main.rs*. Cargo follows a convention that
|
your text editor, and note there’s no mention of *src/main.rs*. Cargo follows a
|
||||||
*src/main.rs* is the crate root of a binary crate with the same name as the
|
convention that *src/main.rs* is the crate root of a binary crate with the same
|
||||||
package. Likewise, Cargo knows that if the package directory contains
|
name as the package. Likewise, Cargo knows that if the package directory
|
||||||
*src/lib.rs*, the package contains a library crate with the same name as the
|
contains *src/lib.rs*, the package contains a library crate with the same name
|
||||||
package, and *src/lib.rs* is its crate root. Cargo passes the crate root files
|
as the package, and *src/lib.rs* is its crate root. Cargo passes the crate root
|
||||||
to `rustc` to build the library or binary.
|
files to `rustc` to build the library or binary.
|
||||||
|
|
||||||
Here, we have a package that only contains *src/main.rs*, meaning it only
|
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 *src/main.rs*
|
contains a binary crate named `my-project`. If a package contains *src/main.rs*
|
||||||
|
|
|
@ -1,27 +1,23 @@
|
||||||
## Defining Modules to Control Scope and Privacy
|
## Defining Modules to Control Scope and Privacy
|
||||||
|
|
||||||
In this section, we’ll talk about modules and other parts of the module system,
|
In this section, we’ll talk about modules and other parts of the module system,
|
||||||
namely *paths* that allow you to name items; the `use` keyword that brings a
|
namely *paths*, which allow you to name items; the `use` keyword that brings a
|
||||||
path into scope; and the `pub` keyword to make items public. We’ll also discuss
|
path into scope; and the `pub` keyword to make items public. We’ll also discuss
|
||||||
the `as` keyword, external packages, and the glob operator.
|
the `as` keyword, external packages, and the glob operator.
|
||||||
|
|
||||||
First, we’re going to start with a list of rules for easy reference when you’re
|
|
||||||
organizing your code in the future. Then we’ll explain each of the rules in
|
|
||||||
detail.
|
|
||||||
|
|
||||||
### Modules Cheat Sheet
|
### Modules Cheat Sheet
|
||||||
|
|
||||||
Here we provide a quick reference on how modules, paths, the `use` keyword, and
|
Before we get to the details of modules and paths, here we provide a quick
|
||||||
the `pub` keyword work in the compiler, and how most developers organize their
|
reference on how modules, paths, the `use` keyword, and the `pub` keyword work
|
||||||
code. We’ll be going through examples of each of these rules throughout this
|
in the compiler, and how most developers organize their code. We’ll be going
|
||||||
chapter, but this is a great place to refer to as a reminder of how modules
|
through examples of each of these rules throughout this chapter, but this is a
|
||||||
work.
|
great place to refer to as a reminder of how modules work.
|
||||||
|
|
||||||
- **Start from the crate root**: When compiling a crate, the compiler first
|
- **Start from the crate root**: When compiling a crate, the compiler first
|
||||||
looks in the crate root file (usually *src/lib.rs* for a library crate or
|
looks in the crate root file (usually *src/lib.rs* for a library crate or
|
||||||
*src/main.rs* for a binary crate) for code to compile.
|
*src/main.rs* for a binary crate) for code to compile.
|
||||||
- **Declaring modules**: In the crate root file, you can declare new modules;
|
- **Declaring modules**: In the crate root file, you can declare new modules;
|
||||||
say, you declare a “garden” module with `mod garden;`. The compiler will look
|
say you declare a “garden” module with `mod garden;`. The compiler will look
|
||||||
for the module’s code in these places:
|
for the module’s code in these places:
|
||||||
- Inline, within curly brackets that replace the semicolon following `mod
|
- Inline, within curly brackets that replace the semicolon following `mod
|
||||||
garden`
|
garden`
|
||||||
|
@ -40,7 +36,7 @@ for the module’s code in these places:
|
||||||
as the privacy rules allow, using the path to the code. For example, an
|
as the privacy rules allow, using the path to the code. For example, an
|
||||||
`Asparagus` type in the garden vegetables module would be found at
|
`Asparagus` type in the garden vegetables module would be found at
|
||||||
`crate::garden::vegetables::Asparagus`.
|
`crate::garden::vegetables::Asparagus`.
|
||||||
- **Private vs public**: Code within a module is private from its parent
|
- **Private vs. public**: Code within a module is private from its parent
|
||||||
modules by default. To make a module public, declare it with `pub mod`
|
modules by default. To make a module public, declare it with `pub mod`
|
||||||
instead of `mod`. To make items within a public module public as well, use
|
instead of `mod`. To make items within a public module public as well, use
|
||||||
`pub` before their declarations.
|
`pub` before their declarations.
|
||||||
|
@ -50,8 +46,9 @@ for the module’s code in these places:
|
||||||
crate::garden::vegetables::Asparagus;` and from then on you only need to
|
crate::garden::vegetables::Asparagus;` and from then on you only need to
|
||||||
write `Asparagus` to make use of that type in the scope.
|
write `Asparagus` to make use of that type in the scope.
|
||||||
|
|
||||||
Here we create a binary crate named `backyard` that illustrates these rules. The
|
Here, we create a binary crate named `backyard` that illustrates these rules.
|
||||||
crate’s directory, also named `backyard`, contains these files and directories:
|
The crate’s directory, also named `backyard`, contains these files and
|
||||||
|
directories:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
backyard
|
backyard
|
||||||
|
@ -93,7 +90,7 @@ Now let’s get into the details of these rules and demonstrate them in action!
|
||||||
### Grouping Related Code in Modules
|
### Grouping Related Code in Modules
|
||||||
|
|
||||||
*Modules* let us organize code within a crate for readability and easy reuse.
|
*Modules* let us organize code within a crate for readability and easy reuse.
|
||||||
Modules also allow us to control the *privacy* of items, because code within a
|
Modules also allow us to control the *privacy* of items because code within a
|
||||||
module is private by default. Private items are internal implementation details
|
module is private by default. Private items are internal implementation details
|
||||||
not available for outside use. We can choose to make modules and the items
|
not available for outside use. We can choose to make modules and the items
|
||||||
within them public, which exposes them to allow external code to use and depend
|
within them public, which exposes them to allow external code to use and depend
|
||||||
|
@ -101,7 +98,7 @@ on them.
|
||||||
|
|
||||||
As an example, let’s write a library crate that provides the functionality of a
|
As an example, let’s write a library crate that provides the functionality of a
|
||||||
restaurant. We’ll define the signatures of functions but leave their bodies
|
restaurant. We’ll define the signatures of functions but leave their bodies
|
||||||
empty to concentrate on the organization of the code, rather than the
|
empty to concentrate on the organization of the code rather than the
|
||||||
implementation of a restaurant.
|
implementation of a restaurant.
|
||||||
|
|
||||||
In the restaurant industry, some parts of a restaurant are referred to as
|
In the restaurant industry, some parts of a restaurant are referred to as
|
||||||
|
@ -113,8 +110,9 @@ administrative work.
|
||||||
|
|
||||||
To structure our crate in this way, we can organize its functions into nested
|
To structure our crate in this way, we can organize its functions into nested
|
||||||
modules. Create a new library named `restaurant` by running `cargo new
|
modules. Create a new library named `restaurant` by running `cargo new
|
||||||
restaurant --lib`; then enter the code in Listing 7-1 into *src/lib.rs* to
|
restaurant --lib`. Then enter the code in Listing 7-1 into *src/lib.rs* to
|
||||||
define some modules and function signatures. Here’s the front of house section:
|
define some modules and function signatures; this code is the front of house
|
||||||
|
section.
|
||||||
|
|
||||||
<span class="filename">Filename: src/lib.rs</span>
|
<span class="filename">Filename: src/lib.rs</span>
|
||||||
|
|
||||||
|
@ -160,13 +158,13 @@ crate
|
||||||
<span class="caption">Listing 7-2: The module tree for the code in Listing
|
<span class="caption">Listing 7-2: The module tree for the code in Listing
|
||||||
7-1</span>
|
7-1</span>
|
||||||
|
|
||||||
This tree shows how some of the modules nest inside one another; for example,
|
This tree shows how some of the modules nest inside other modules; for example,
|
||||||
`hosting` nests inside `front_of_house`. The tree also shows that some modules
|
`hosting` nests inside `front_of_house`. The tree also shows that some modules
|
||||||
are *siblings* to each other, meaning they’re defined in the same module;
|
are *siblings*, meaning they’re defined in the same module; `hosting` and
|
||||||
`hosting` and `serving` are siblings defined within `front_of_house`. If module
|
`serving` are siblings defined within `front_of_house`. If module A is
|
||||||
A is contained inside module B, we say that module A is the *child* of module B
|
contained inside module B, we say that module A is the *child* of module B and
|
||||||
and that module B is the *parent* of module A. Notice that the entire module
|
that module B is the *parent* of module A. Notice that the entire module tree
|
||||||
tree is rooted under the implicit module named `crate`.
|
is rooted under the implicit module named `crate`.
|
||||||
|
|
||||||
The module tree might remind you of the filesystem’s directory tree on your
|
The module tree might remind you of the filesystem’s directory tree on your
|
||||||
computer; this is a very apt comparison! Just like directories in a filesystem,
|
computer; this is a very apt comparison! Just like directories in a filesystem,
|
||||||
|
|
|
@ -20,10 +20,10 @@ This is the same as asking: what’s the path of the `add_to_waitlist` function?
|
||||||
Listing 7-3 contains Listing 7-1 with some of the modules and functions
|
Listing 7-3 contains Listing 7-1 with some of the modules and functions
|
||||||
removed.
|
removed.
|
||||||
|
|
||||||
We’ll show two ways to call the `add_to_waitlist` function from a new function
|
We’ll show two ways to call the `add_to_waitlist` function from a new function,
|
||||||
`eat_at_restaurant` defined in the crate root. These paths are correct, but
|
`eat_at_restaurant`, defined in the crate root. These paths are correct, but
|
||||||
there’s another problem remaining that will prevent this example from compiling
|
there’s another problem remaining that will prevent this example from compiling
|
||||||
as-is. We’ll explain why in a bit.
|
as is. We’ll explain why in a bit.
|
||||||
|
|
||||||
The `eat_at_restaurant` function is part of our library crate’s public API, so
|
The `eat_at_restaurant` function is part of our library crate’s public API, so
|
||||||
we mark it with the `pub` keyword. In the [“Exposing Paths with the `pub`
|
we mark it with the `pub` keyword. In the [“Exposing Paths with the `pub`
|
||||||
|
@ -55,19 +55,20 @@ filesystem equivalent would be using the path
|
||||||
that the path is relative.
|
that the path is relative.
|
||||||
|
|
||||||
Choosing whether to use a relative or absolute path is a decision you’ll make
|
Choosing whether to use a relative or absolute path is a decision you’ll make
|
||||||
based on your project, and depends on whether you’re more likely to move item
|
based on your project, and it depends on whether you’re more likely to move
|
||||||
definition code separately from or together with the code that uses the item.
|
item definition code separately from or together with the code that uses the
|
||||||
For example, if we move the `front_of_house` module and the `eat_at_restaurant`
|
item. For example, if we moved the `front_of_house` module and the
|
||||||
function into a module named `customer_experience`, we’d need to update the
|
`eat_at_restaurant` function into a module named `customer_experience`, we’d
|
||||||
absolute path to `add_to_waitlist`, but the relative path would still be valid.
|
need to update the absolute path to `add_to_waitlist`, but the relative path
|
||||||
However, if we moved the `eat_at_restaurant` function separately into a module
|
would still be valid. However, if we moved the `eat_at_restaurant` function
|
||||||
named `dining`, the absolute path to the `add_to_waitlist` call would stay the
|
separately into a module named `dining`, the absolute path to the
|
||||||
same, but the relative path would need to be updated. Our preference in general
|
`add_to_waitlist` call would stay the same, but the relative path would need to
|
||||||
is to specify absolute paths because it’s more likely we’ll want to move code
|
be updated. Our preference in general is to specify absolute paths because it’s
|
||||||
definitions and item calls independently of each other.
|
more likely we’ll want to move code definitions and item calls independently of
|
||||||
|
each other.
|
||||||
|
|
||||||
Let’s try to compile Listing 7-3 and find out why it won’t compile yet! The
|
Let’s try to compile Listing 7-3 and find out why it won’t compile yet! The
|
||||||
error we get is shown in Listing 7-4.
|
errors we get are shown in Listing 7-4.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
{{#include ../listings/ch07-managing-growing-projects/listing-07-03/output.txt}}
|
{{#include ../listings/ch07-managing-growing-projects/listing-07-03/output.txt}}
|
||||||
|
@ -113,8 +114,8 @@ access to the `add_to_waitlist` function in the child module, so we mark the
|
||||||
<span class="caption">Listing 7-5: Declaring the `hosting` module as `pub` to
|
<span class="caption">Listing 7-5: Declaring the `hosting` module as `pub` to
|
||||||
use it from `eat_at_restaurant`</span>
|
use it from `eat_at_restaurant`</span>
|
||||||
|
|
||||||
Unfortunately, the code in Listing 7-5 still results in an error, as shown in
|
Unfortunately, the code in Listing 7-5 still results in compiler errors, as
|
||||||
Listing 7-6.
|
shown in Listing 7-6.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
{{#include ../listings/ch07-managing-growing-projects/listing-07-05/output.txt}}
|
{{#include ../listings/ch07-managing-growing-projects/listing-07-05/output.txt}}
|
||||||
|
@ -180,13 +181,13 @@ interested in this topic, see [The Rust API Guidelines][api-guidelines].
|
||||||
|
|
||||||
> #### Best Practices for Packages with a Binary and a Library
|
> #### Best Practices for Packages with a Binary and a Library
|
||||||
>
|
>
|
||||||
> We mentioned a package can contain both a *src/main.rs* binary crate root as
|
> We mentioned that a package can contain both a *src/main.rs* binary crate
|
||||||
> well as a *src/lib.rs* library crate root, and both crates will have the
|
> root as well as a *src/lib.rs* library crate root, and both crates will have
|
||||||
> package name by default. Typically, packages with this pattern of containing
|
> the package name by default. Typically, packages with this pattern of
|
||||||
> both a library and a binary crate will have just enough code in the binary
|
> containing both a library and a binary crate will have just enough code in the
|
||||||
> crate to start an executable that calls code within the library crate. This
|
> binary crate to start an executable that calls code within the library crate.
|
||||||
> lets other projects benefit from most of the functionality that the package
|
> This lets other projects benefit from most of the functionality that the
|
||||||
> provides, because the library crate’s code can be shared.
|
> package provides because the library crate’s code can be shared.
|
||||||
>
|
>
|
||||||
> The module tree should be defined in *src/lib.rs*. Then, any public items can
|
> The module tree should be defined in *src/lib.rs*. Then, any public items can
|
||||||
> be used in the binary crate by starting paths with the name of the package.
|
> be used in the binary crate by starting paths with the name of the package.
|
||||||
|
@ -206,14 +207,14 @@ the current module or the crate root, by using `super` at the start of the
|
||||||
path. This is like starting a filesystem path with the `..` syntax. Using
|
path. This is like starting a filesystem path with the `..` syntax. Using
|
||||||
`super` allows us to reference an item that we know is in the parent module,
|
`super` allows us to reference an item that we know is in the parent module,
|
||||||
which can make rearranging the module tree easier when the module is closely
|
which can make rearranging the module tree easier when the module is closely
|
||||||
related to the parent, but the parent might be moved elsewhere in the module
|
related to the parent but the parent might be moved elsewhere in the module
|
||||||
tree someday.
|
tree someday.
|
||||||
|
|
||||||
Consider the code in Listing 7-8 that models the situation in which a chef
|
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
|
fixes an incorrect order and personally brings it out to the customer. The
|
||||||
function `fix_incorrect_order` defined in the `back_of_house` module calls the
|
function `fix_incorrect_order` defined in the `back_of_house` module calls the
|
||||||
function `deliver_order` defined in the parent module by specifying the path to
|
function `deliver_order` defined in the parent module by specifying the path to
|
||||||
`deliver_order` starting with `super`:
|
`deliver_order`, starting with `super`.
|
||||||
|
|
||||||
<span class="filename">Filename: src/lib.rs</span>
|
<span class="filename">Filename: src/lib.rs</span>
|
||||||
|
|
||||||
|
@ -236,7 +237,7 @@ code gets moved to a different module.
|
||||||
### Making Structs and Enums Public
|
### Making Structs and Enums Public
|
||||||
|
|
||||||
We can also use `pub` to designate structs and enums as public, but there are a
|
We can also use `pub` to designate structs and enums as public, but there are a
|
||||||
few details extra to the usage of `pub` with structs and enums. If we use `pub`
|
few extra details to the usage of `pub` with structs and enums. If we use `pub`
|
||||||
before a struct definition, we make the struct public, but the struct’s fields
|
before a struct definition, we make the struct public, but the struct’s fields
|
||||||
will still be private. We can make each field public or not on a case-by-case
|
will still be private. We can make each field public or not on a case-by-case
|
||||||
basis. In Listing 7-9, we’ve defined a public `back_of_house::Breakfast` struct
|
basis. In Listing 7-9, we’ve defined a public `back_of_house::Breakfast` struct
|
||||||
|
@ -258,7 +259,7 @@ private fields</span>
|
||||||
Because the `toast` field in 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
|
in `eat_at_restaurant` we can write and read to the `toast` field using dot
|
||||||
notation. Notice that we can’t use the `seasonal_fruit` field in
|
notation. Notice that we can’t use the `seasonal_fruit` field in
|
||||||
`eat_at_restaurant` because `seasonal_fruit` is private. Try uncommenting the
|
`eat_at_restaurant`, because `seasonal_fruit` is private. Try uncommenting the
|
||||||
line modifying the `seasonal_fruit` field value to see what error you get!
|
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
|
||||||
|
|
|
@ -30,7 +30,7 @@ also check privacy, like any other paths.
|
||||||
Note that `use` only creates the shortcut for the particular scope in which the
|
Note that `use` only creates the shortcut for the particular scope in which the
|
||||||
`use` occurs. Listing 7-12 moves the `eat_at_restaurant` function into a new
|
`use` occurs. Listing 7-12 moves the `eat_at_restaurant` function into a new
|
||||||
child module named `customer`, which is then a different scope than the `use`
|
child module named `customer`, which is then a different scope than the `use`
|
||||||
statement, so the function body won’t compile:
|
statement, so the function body won’t compile.
|
||||||
|
|
||||||
<span class="filename">Filename: src/lib.rs</span>
|
<span class="filename">Filename: src/lib.rs</span>
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ the shortcut in the parent module with `super::hosting` within the child
|
||||||
|
|
||||||
In Listing 7-11, you might 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
|
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
|
`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.
|
the `add_to_waitlist` function to achieve the same result, as in Listing 7-13.
|
||||||
|
|
||||||
<span class="filename">Filename: src/lib.rs</span>
|
<span class="filename">Filename: src/lib.rs</span>
|
||||||
|
@ -69,9 +69,9 @@ the `add_to_waitlist` function to achieve the same result, as in Listing 7-13.
|
||||||
<span class="caption">Listing 7-13: Bringing the `add_to_waitlist` function
|
<span class="caption">Listing 7-13: Bringing the `add_to_waitlist` function
|
||||||
into scope with `use`, which is unidiomatic</span>
|
into scope with `use`, which is unidiomatic</span>
|
||||||
|
|
||||||
Although both Listing 7-11 and 7-13 accomplish the same task, Listing 7-11 is
|
Although both Listing 7-11 and Listing 7-13 accomplish the same task, Listing
|
||||||
the idiomatic way to bring a function into scope with `use`. Bringing the
|
7-11 is the idiomatic way to bring a function into scope with `use`. Bringing
|
||||||
function’s parent module into scope with `use` means we have to specify the
|
the function’s parent module into scope with `use` means we have to specify the
|
||||||
parent module when calling the function. Specifying the parent module when
|
parent module when calling the function. Specifying the parent module when
|
||||||
calling the function makes it clear that the function isn’t locally defined
|
calling the function makes it clear that the function isn’t locally defined
|
||||||
while still minimizing repetition of the full path. The code in Listing 7-13 is
|
while still minimizing repetition of the full path. The code in Listing 7-13 is
|
||||||
|
@ -97,7 +97,7 @@ emerged, and folks have gotten used to reading and writing Rust code this way.
|
||||||
The exception to this idiom is if we’re bringing two items with the same name
|
The exception to this idiom is if we’re bringing two items with the same name
|
||||||
into scope with `use` statements, because Rust doesn’t allow that. Listing 7-15
|
into scope with `use` statements, because Rust doesn’t allow that. Listing 7-15
|
||||||
shows how to bring two `Result` types into scope that have the same name but
|
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>
|
<span class="filename">Filename: src/lib.rs</span>
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ the same scope requires using their parent modules.</span>
|
||||||
|
|
||||||
As you can see, using the parent modules distinguishes the two `Result` types.
|
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`, we’d
|
If instead we specified `use std::fmt::Result` and `use std::io::Result`, we’d
|
||||||
have two `Result` types in the same scope and Rust wouldn’t know which one we
|
have two `Result` types in the same scope, and Rust wouldn’t know which one we
|
||||||
meant when we used `Result`.
|
meant when we used `Result`.
|
||||||
|
|
||||||
### Providing New Names with the `as` Keyword
|
### Providing New Names with the `as` Keyword
|
||||||
|
@ -139,8 +139,8 @@ considered idiomatic, so the choice is up to you!
|
||||||
When we bring a name into scope with the `use` keyword, the name available in
|
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
|
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 code’s scope, we can combine `pub`
|
that name as if it had been defined in that code’s scope, we can combine `pub`
|
||||||
and `use`. This technique is called *re-exporting* because we’re bringing
|
and `use`. This technique is called *re-exporting* because we’re bringing an
|
||||||
an item into scope but also making that item available for others to bring into
|
item into scope but also making that item available for others to bring into
|
||||||
their scope.
|
their scope.
|
||||||
|
|
||||||
Listing 7-17 shows the code in Listing 7-11 with `use` in the root module
|
Listing 7-17 shows the code in Listing 7-11 with `use` in the root module
|
||||||
|
@ -160,7 +160,7 @@ function by using the path
|
||||||
`restaurant::front_of_house::hosting::add_to_waitlist()`, which also would have
|
`restaurant::front_of_house::hosting::add_to_waitlist()`, which also would have
|
||||||
required the `front_of_house` module to be marked as `pub`. Now that this `pub
|
required the `front_of_house` module to be marked as `pub`. Now that this `pub
|
||||||
use` has re-exported the `hosting` module from the root module, external code
|
use` has re-exported the `hosting` module from the root module, external code
|
||||||
can now use the path `restaurant::hosting::add_to_waitlist()` instead.
|
can use the path `restaurant::hosting::add_to_waitlist()` instead.
|
||||||
|
|
||||||
Re-exporting is useful when the internal structure of your code is different
|
Re-exporting is useful when the internal structure of your code is different
|
||||||
from how programmers calling your code would think about the domain. For
|
from how programmers calling your code would think about the domain. For
|
||||||
|
@ -226,10 +226,10 @@ crate.
|
||||||
|
|
||||||
### Using Nested Paths to Clean Up Large `use` Lists
|
### Using Nested Paths to Clean Up Large `use` Lists
|
||||||
|
|
||||||
If we’re using multiple items defined in the same crate or same module,
|
If we’re using multiple items defined in the same crate or same module, listing
|
||||||
listing each item on its own line can take up a lot of vertical space in our
|
each item on its own line can take up a lot of vertical space in our files. For
|
||||||
files. For example, these two `use` statements we had in the Guessing Game in
|
example, these two `use` statements we had in the guessing game in Listing 2-4
|
||||||
Listing 2-4 bring items from `std` into scope:
|
bring items from `std` into scope:
|
||||||
|
|
||||||
<span class="filename">Filename: src/main.rs</span>
|
<span class="filename">Filename: src/main.rs</span>
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ modules defined in the crate root file. In this case, the crate root file is
|
||||||
*src/lib.rs*, but this procedure also works with binary crates whose crate root
|
*src/lib.rs*, but this procedure also works with binary crates whose crate root
|
||||||
file is *src/main.rs*.
|
file is *src/main.rs*.
|
||||||
|
|
||||||
First, we’ll extract the `front_of_house` module to its own file. Remove the
|
First we’ll extract the `front_of_house` module to its own file. Remove the
|
||||||
code inside the curly brackets for the `front_of_house` module, leaving only
|
code inside the curly brackets for the `front_of_house` module, leaving only
|
||||||
the `mod front_of_house;` declaration, so that *src/lib.rs* contains the code
|
the `mod front_of_house;` declaration, so that *src/lib.rs* contains the code
|
||||||
shown in Listing 7-21. Note that this won’t compile until we create the
|
shown in Listing 7-21. Note that this won’t compile until we create the
|
||||||
|
@ -51,10 +51,10 @@ programming languages.
|
||||||
Next, we’ll extract the `hosting` module to its own file. The process is a bit
|
Next, we’ll extract the `hosting` module to its own file. The process is a bit
|
||||||
different because `hosting` is a child module of `front_of_house`, not of the
|
different because `hosting` is a child module of `front_of_house`, not of the
|
||||||
root module. We’ll place the file for `hosting` in a new directory that will be
|
root module. We’ll place the file for `hosting` in a new directory that will be
|
||||||
named for its ancestors in the module tree, in this case *src/front_of_house/*.
|
named for its ancestors in the module tree, in this case *src/front_of_house*.
|
||||||
|
|
||||||
To start moving `hosting`, we change *src/front_of_house.rs* to contain only the
|
To start moving `hosting`, we change *src/front_of_house.rs* to contain only
|
||||||
declaration of the `hosting` module:
|
the declaration of the `hosting` module:
|
||||||
|
|
||||||
<span class="filename">Filename: src/front_of_house.rs</span>
|
<span class="filename">Filename: src/front_of_house.rs</span>
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ declaration of the `hosting` module:
|
||||||
{{#rustdoc_include ../listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/front_of_house.rs}}
|
{{#rustdoc_include ../listings/ch07-managing-growing-projects/no-listing-02-extracting-hosting/src/front_of_house.rs}}
|
||||||
```
|
```
|
||||||
|
|
||||||
Then we create a *src/front_of_house* directory and a file *hosting.rs* to
|
Then we create a *src/front_of_house* directory and a *hosting.rs* file to
|
||||||
contain the definitions made in the `hosting` module:
|
contain the definitions made in the `hosting` module:
|
||||||
|
|
||||||
<span class="filename">Filename: src/front_of_house/hosting.rs</span>
|
<span class="filename">Filename: src/front_of_house/hosting.rs</span>
|
||||||
|
@ -74,7 +74,7 @@ contain the definitions made in the `hosting` module:
|
||||||
If we instead put *hosting.rs* in the *src* directory, the compiler would
|
If we instead put *hosting.rs* in the *src* directory, the compiler would
|
||||||
expect the *hosting.rs* code to be in a `hosting` module declared in the crate
|
expect the *hosting.rs* code to be in a `hosting` module declared in the crate
|
||||||
root, and not declared as a child of the `front_of_house` module. The
|
root, and not declared as a child of the `front_of_house` module. The
|
||||||
compiler’s rules for which files to check for which modules’ code means the
|
compiler’s rules for which files to check for which modules’ code mean the
|
||||||
directories and files more closely match the module tree.
|
directories and files more closely match the module tree.
|
||||||
|
|
||||||
> ### Alternate File Paths
|
> ### Alternate File Paths
|
||||||
|
@ -93,9 +93,9 @@ directories and files more closely match the module tree.
|
||||||
> * *src/front_of_house/hosting.rs* (what we covered)
|
> * *src/front_of_house/hosting.rs* (what we covered)
|
||||||
> * *src/front_of_house/hosting/mod.rs* (older style, still supported path)
|
> * *src/front_of_house/hosting/mod.rs* (older style, still supported path)
|
||||||
>
|
>
|
||||||
> If you use both styles for the same module, you’ll get a compiler error. Using
|
> If you use both styles for the same module, you’ll get a compiler error.
|
||||||
> a mix of both styles for different modules in the same project is allowed, but
|
> Using a mix of both styles for different modules in the same project is
|
||||||
> might be confusing for people navigating your project.
|
> allowed, but might be confusing for people navigating your project.
|
||||||
>
|
>
|
||||||
> The main downside to the style that uses files named *mod.rs* is that your
|
> The main downside to the style that uses files named *mod.rs* is that your
|
||||||
> project can end up with many files named *mod.rs*, which can get confusing
|
> project can end up with many files named *mod.rs*, which can get confusing
|
||||||
|
@ -114,8 +114,8 @@ that module.
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
Rust lets you split a package into multiple crates and a crate into modules
|
Rust lets you split a package into multiple crates and a crate into modules so
|
||||||
so you can refer to items defined in one module from another module. You can do
|
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
|
this by specifying absolute or relative paths. These paths can be brought into
|
||||||
scope with a `use` statement so you can use a shorter path for multiple uses of
|
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
|
the item in that scope. Module code is private by default, but you can make
|
||||||
|
|
Loading…
Reference in New Issue