From f954cb859fa3765f152b62337d8fd07dfa53f1ab Mon Sep 17 00:00:00 2001 From: "Carol (Nichols || Goulding)" Date: Thu, 25 Apr 2024 16:47:51 -0400 Subject: [PATCH] Snapshot changes to generated ch7 that SHOULDN'T be sent to nostarch This snapshot contains line wrapping problems, irrelevant comments, extraneous output lines, and differences we're going to allow between the online and print version. The intention is to make this a baseline commit for chapter 7 that we can diff against to find changes to consider sending to nostarch as tiny tweaks. --- nostarch/chapter07.md | 469 +++++++++++++++++++++++------------------- 1 file changed, 260 insertions(+), 209 deletions(-) diff --git a/nostarch/chapter07.md b/nostarch/chapter07.md index 8b2dce77..7e09e61e 100644 --- a/nostarch/chapter07.md +++ b/nostarch/chapter07.md @@ -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 these techniques. For very large projects comprising a set of interrelated 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 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 collectively referred to as the *module system*, include: -* **Packages **: A Cargo feature that lets you build, test, and share crates -* **Crates**: A tree of modules that produces a library or executable -* **Modules and use**: Let you control the organization, scope, and privacy of -paths -* **Paths **: A way of naming an item, such as a struct, function, or module +* **Packages:** A Cargo feature that lets you build, test, and share crates +* **Crates:** A tree of modules that produces a library or executable +* **Modules** and **use:** Let you control the organization, scope, and + privacy of paths +* **Paths:** A way of naming an item, such as a struct, function, or module In this chapter, 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 @@ -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 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 -page XX), the compiler considers that file to be a crate. Crates can contain -modules, and the modules may be defined in other files that get compiled with -the crate, as we’ll see in the coming sections. +file (as we did all the way back in the “Writing and Running a Rust Program” +section of Chapter 1), the compiler considers that file to be a crate. Crates +can contain modules, and the modules may be defined in other files that get +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. *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 created so far have been binary crates. *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 -multiple projects. For example, the `rand` crate we used in Chapter 2 provides -functionality that generates random numbers. Most of the time when Rustaceans -say “crate,” they mean library crate, and they use “crate” interchangeably with -the general programming concept of a “library.” +multiple projects. For example, the `rand` crate we used in Chapter +2 provides functionality that generates random numbers. +Most of the time when Rustaceans say “crate”, they mean library crate, and they +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 -up the root module of your crate (we’ll explain modules in depth in “Defining -Modules to Control Scope and Privacy” on page XX). +up the root module of your crate (we’ll explain modules in depth in the +“Defining Modules to Control Scope and Privacy” +section). 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 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 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 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 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 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 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 also allow us to control the *privacy* of items because code within a 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 -contain functions +Listing 7-1: A `front_of_house` module containing other +modules that then contain functions 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 @@ -298,7 +303,8 @@ crate └── 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, `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: -* An *absolute path* is the full path starting from a crate root; for code from -an external crate, the absolute path begins with the crate name, and for code -from the current crate, it starts with the literal `crate`. +* An *absolute path* is the full path starting from a crate root; for code + from an external crate, the absolute path begins with the crate name, and for + code from the current crate, it starts with the literal `crate`. * 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 separated by double colons (`::`). 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? -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, `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. 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 -page XX, we’ll go into more detail about `pub`. +we mark it with the `pub` keyword. In the “Exposing Paths with the `pub` +Keyword” section, we’ll go into more detail about `pub`. 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 -paths +Listing 7-3: Calling the `add_to_waitlist` function using +absolute and relative paths 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 @@ -422,9 +429,13 @@ note: the module `hosting` is defined here | 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 have the correct paths for the `hosting` module and the `add_to_waitlist` @@ -447,7 +458,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 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 private. We want the `eat_at_restaurant` function in the parent module to have @@ -463,11 +474,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 -`eat_at_restaurant` +Listing 7-5: Declaring the `hosting` module as `pub` to +use it from `eat_at_restaurant` Unfortunately, the code in Listing 7-5 still results in compiler errors, as shown in Listing 7-6. @@ -498,9 +515,13 @@ note: the function `add_to_waitlist` is defined here | 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 module public. With this change, if we can access `front_of_house`, we can @@ -527,11 +548,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` -lets us call the function from `eat_at_restaurant`. +Listing 7-7: Adding the `pub` keyword to `mod hosting` +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 these paths in `add_to_waitlist` with respect to the privacy rules, let’s look @@ -559,31 +587,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 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 -crate. These considerations are beyond the scope of this book; if you’re -interested in this topic, see the Rust API Guidelines at -*https://rust-lang.github.io/api-guidelines*. +crate. These considerations are out of the scope of this book; if you’re +interested in this topic, see The Rust API Guidelines at *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 -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 -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. -This lets other projects benefit from the most functionality that the package -provides because the library crate’s code can be shared. +> 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 +> 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. +> This lets other projects benefit from the most functionality that the +> 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 -be used in the binary crate by starting paths with the name of the package. 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. -This helps you design a good API; not only are you the author, you’re also a -client! +> be used in the binary crate by starting paths with the name of the package. +> 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. +> This helps you design a good API; not only are you the author, you’re also a +> client! > -> In Chapter 12, we’ll demonstrate this organizational practice with a command -line program that will contain both a binary crate and a library crate. +> In Chapter 12, we’ll demonstrate this organizational +> 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 the current module or the crate root, by using `super` at the start of the @@ -614,7 +642,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 use `super` to go to the parent module of `back_of_house`, which in this case @@ -664,14 +693,14 @@ pub fn eat_at_restaurant() { meal.toast = String::from("Wheat"); println!("I'd like {} toast please", meal.toast); - // The next line won't compile if we uncomment it; we're not - // allowed to see or modify the seasonal fruit that comes - // with the meal + // The next line won't compile if we uncomment it; we're not allowed + // to see or modify the seasonal fruit that comes with the meal // 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, in `eat_at_restaurant` we can write and read to the `toast` field using dot @@ -705,7 +734,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` variants in `eat_at_restaurant`. @@ -720,7 +750,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 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 repetitive. In Listing 7-7, whether we chose the absolute or relative path to @@ -750,7 +780,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 the filesystem. By adding `use crate::front_of_house::hosting` in the crate @@ -781,12 +812,15 @@ 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 `customer` module: ``` +$ cargo build + Compiling restaurant v0.1.0 (file:///projects/restaurant) error[E0433]: failed to resolve: use of undeclared crate or module `hosting` --> src/lib.rs:11:9 | @@ -800,6 +834,10 @@ warning: unused import: `crate::front_of_house::hosting` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = 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 @@ -807,7 +845,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 `customer` module. -### Creating Idiomatic use Paths +### Creating Idiomatic `use` Paths 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 @@ -830,8 +868,8 @@ pub fn eat_at_restaurant() { } ``` -Listing 7-13: Bringing the `add_to_waitlist` function into scope with `use`, -which is unidiomatic +Listing 7-13: Bringing the `add_to_waitlist` function +into scope with `use`, which is unidiomatic 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 @@ -857,7 +895,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 emerged, and folks have gotten used to reading and writing Rust code this way. @@ -874,23 +913,23 @@ use std::fmt; use std::io; fn function1() -> fmt::Result { - --snip-- + // --snip-- } fn function2() -> io::Result<()> { - --snip-- + // --snip-- } ``` -Listing 7-15: Bringing two types with the same name into the same scope -requires using their parent modules. +Listing 7-15: Bringing two types with the same name into +the same scope requires using their parent modules. 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 have two `Result` types in the same scope, and Rust wouldn’t know which one we 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 into the same scope with `use`: after the path, we can specify `as` and a new @@ -904,22 +943,23 @@ use std::fmt::Result; use std::io::Result as IoResult; fn function1() -> Result { - --snip-- + // --snip-- } 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 `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 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 the new scope is private. To enable the code that calls our code to refer to @@ -947,8 +987,8 @@ pub fn eat_at_restaurant() { } ``` -Listing 7-17: Making a name available for any code to use from a new scope with -`pub use` +Listing 7-17: Making a name available for any code to use +from a new scope with `pub use` Before this change, external code would have to call the `add_to_waitlist` function by using the path @@ -964,8 +1004,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 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 -of `pub use` and how it affects your crate’s documentation in “Exporting a -Convenient Public API with pub use” on page XX. +of `pub use` and how it affects your crate’s documentation in the “Exporting a +Convenient Public API with `pub use`” section of +Chapter 14. ### Using External Packages @@ -973,6 +1014,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 added this line to *Cargo.toml*: + + Filename: Cargo.toml ``` @@ -980,14 +1027,14 @@ rand = "0.8.5" ``` 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` -available to our project. +`rand` package and any dependencies from crates.io at *https://crates.io/* and +make `rand` available to our project. Then, to bring `rand` definitions into the scope of our package, we added a -`use` line starting with the name of the crate, `rand`, and listed the items we -wanted to bring into scope. Recall that in “Generating a Random Number” on page -XX, we brought the `Rng` trait into scope and called the `rand::thread_rng` -function: +`use` line starting with the name of the crate, `rand`, and listed the items +we wanted to bring into scope. Recall that in the “Generating a Random +Number” section in Chapter 2, we brought the `Rng` trait +into scope and called the `rand::thread_rng` function: ``` use rand::Rng; @@ -998,9 +1045,9 @@ fn main() { ``` Members of the Rust community have made many packages available at -*https://crates.io*, and pulling any of them into your package involves these -same steps: listing them in your package’s *Cargo.toml* file and using `use` to -bring items from their crates into scope. +crates.io at *https://crates.io/*, and pulling any of them into your package +involves these same steps: listing them in your package’s *Cargo.toml* file and +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 package. Because the standard library is shipped with the Rust language, we @@ -1015,7 +1062,7 @@ use std::collections::HashMap; This is an absolute path starting with `std`, the name of the standard library 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 each item on its own line can take up a lot of vertical space in our files. For @@ -1025,10 +1072,10 @@ bring items from `std` into scope: Filename: src/main.rs ``` ---snip-- +// --snip-- use std::cmp::Ordering; use std::io; ---snip-- +// --snip-- ``` Instead, we can use nested paths to bring the same items into scope in one @@ -1039,13 +1086,13 @@ differ, as shown in Listing 7-18. Filename: src/main.rs ``` ---snip-- +// --snip-- use std::{cmp::Ordering, io}; ---snip-- +// --snip-- ``` -Listing 7-18: Specifying a nested path to bring multiple items with the same -prefix into scope +Listing 7-18: Specifying a nested path to bring multiple +items with the same prefix into scope 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 @@ -1063,7 +1110,8 @@ use std::io; 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 path. To merge these two paths into one `use` statement, we can use `self` in @@ -1075,7 +1123,8 @@ Filename: src/lib.rs 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. @@ -1094,9 +1143,11 @@ harder to tell what names are in scope and where a name used in your program was defined. The glob operator is often used when testing to bring everything under test -into the `tests` module; we’ll talk about that in “How to Write Tests” on page -XX. The glob operator is also sometimes used as part of the prelude pattern: -see the standard library documentation for more information on that pattern. +into the `tests` module; we’ll talk about that in the “How to Write +Tests” section in Chapter 11. The glob operator +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 @@ -1128,8 +1179,8 @@ pub fn eat_at_restaurant() { } ``` -Listing 7-21: Declaring the `front_of_house` module whose body will be in -*src/front_of_house.rs* +Listing 7-21: Declaring the `front_of_house` module whose +body will be in *src/front_of_house.rs* 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 @@ -1144,16 +1195,17 @@ pub mod hosting { } ``` -Listing 7-22: Definitions inside the `front_of_house` module in -*src/front_of_house.rs* +Listing 7-22: Definitions inside the `front_of_house` +module in *src/front_of_house.rs* 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 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 -using a path to where it was declared, as covered in “Paths for Referring to an -Item in the Module Tree” on page XX. In other words, `mod` is *not* an -“include” operation that you may have seen in other programming languages. +using a path to where it was declared, as covered in the “Paths for Referring +to an Item in the Module Tree” section. In other words, +`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 different because `hosting` is a child module of `front_of_house`, not of the @@ -1187,26 +1239,26 @@ directories and files more closely match the module tree. > ### Alternate File Paths > > 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 -`front_of_house` declared in the crate root, the compiler will look for the -module’s code in: +> 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 +> module’s code in: > > * *src/front_of_house.rs* (what we covered) > * *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 -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/mod.rs* (older style, still supported path) > > 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 -allowed, but might be confusing for people navigating your project. +> Using a mix of both styles for different modules in the same project is +> 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 -project can end up with many files named *mod.rs*, which can get confusing when -you have them open in your editor at the same time. +> project can end up with many files named *mod.rs*, which can get confusing +> 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 the same. The function calls in `eat_at_restaurant` will work without any @@ -1230,4 +1282,3 @@ definitions public by adding the `pub` keyword. 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. -