]>
Commit | Line | Data |
---|---|---|
532ac7d7 XL |
1 | ## Bringing Paths into Scope with the `use` Keyword |
2 | ||
3 | It might seem like the paths we’ve written to call functions so far are | |
4 | inconveniently long and repetitive. For example, in Listing 7-7, whether we | |
5 | chose the absolute or relative path to the `add_to_waitlist` function, every | |
6 | time we wanted to call `add_to_waitlist` we had to specify `front_of_house` and | |
7 | `hosting` too. Fortunately, there’s a way to simplify this process. We can | |
8 | bring a path into a scope once and then call the items in that path as if | |
9 | they’re local items with the `use` keyword. | |
10 | ||
11 | In Listing 7-11, we bring the `crate::front_of_house::hosting` module into the | |
12 | scope of the `eat_at_restaurant` function so we only have to specify | |
13 | `hosting::add_to_waitlist` to call the `add_to_waitlist` function in | |
14 | `eat_at_restaurant`. | |
15 | ||
16 | <span class="filename">Filename: src/lib.rs</span> | |
17 | ||
fc512014 XL |
18 | ```rust,noplayground,test_harness |
19 | {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-11/src/lib.rs}} | |
532ac7d7 XL |
20 | ``` |
21 | ||
22 | <span class="caption">Listing 7-11: Bringing a module into scope with | |
23 | `use`</span> | |
24 | ||
25 | Adding `use` and a path in a scope is similar to creating a symbolic link in | |
26 | the filesystem. By adding `use crate::front_of_house::hosting` in the crate | |
27 | root, `hosting` is now a valid name in that scope, just as though the `hosting` | |
28 | module had been defined in the crate root. Paths brought into scope with `use` | |
29 | also check privacy, like any other paths. | |
30 | ||
e1599b0c XL |
31 | You can also bring an item into scope with `use` and a relative path. Listing |
32 | 7-12 shows how to specify a relative path to get the same behavior as in | |
33 | Listing 7-11. | |
532ac7d7 XL |
34 | |
35 | <span class="filename">Filename: src/lib.rs</span> | |
36 | ||
fc512014 XL |
37 | ```rust,noplayground,test_harness |
38 | {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-12/src/lib.rs}} | |
532ac7d7 XL |
39 | ``` |
40 | ||
41 | <span class="caption">Listing 7-12: Bringing a module into scope with `use` and | |
e1599b0c | 42 | a relative path</span> |
532ac7d7 XL |
43 | |
44 | ### Creating Idiomatic `use` Paths | |
45 | ||
46 | In Listing 7-11, you might have wondered why we specified `use | |
47 | crate::front_of_house::hosting` and then called `hosting::add_to_waitlist` in | |
48 | `eat_at_restaurant` rather than specifying the `use` path all the way out to | |
49 | the `add_to_waitlist` function to achieve the same result, as in Listing 7-13. | |
50 | ||
51 | <span class="filename">Filename: src/lib.rs</span> | |
52 | ||
fc512014 XL |
53 | ```rust,noplayground,test_harness |
54 | {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-13/src/lib.rs}} | |
532ac7d7 XL |
55 | ``` |
56 | ||
57 | <span class="caption">Listing 7-13: Bringing the `add_to_waitlist` function | |
58 | into scope with `use`, which is unidiomatic</span> | |
59 | ||
60 | Although both Listing 7-11 and 7-13 accomplish the same task, Listing 7-11 is | |
61 | the idiomatic way to bring a function into scope with `use`. Bringing the | |
136023e0 XL |
62 | function’s parent module into scope with `use` means we have to specify the |
63 | parent module when calling the function. Specifying the parent module when | |
64 | calling the function makes it clear that the function isn’t locally defined | |
65 | while still minimizing repetition of the full path. The code in Listing 7-13 is | |
66 | unclear as to where `add_to_waitlist` is defined. | |
532ac7d7 XL |
67 | |
68 | On the other hand, when bringing in structs, enums, and other items with `use`, | |
69 | it’s idiomatic to specify the full path. Listing 7-14 shows the idiomatic way | |
70 | to bring the standard library’s `HashMap` struct into the scope of a binary | |
71 | crate. | |
72 | ||
73 | <span class="filename">Filename: src/main.rs</span> | |
74 | ||
75 | ```rust | |
74b04a01 | 76 | {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-14/src/main.rs}} |
532ac7d7 XL |
77 | ``` |
78 | ||
79 | <span class="caption">Listing 7-14: Bringing `HashMap` into scope in an | |
80 | idiomatic way</span> | |
81 | ||
82 | There’s no strong reason behind this idiom: it’s just the convention that has | |
83 | emerged, and folks have gotten used to reading and writing Rust code this way. | |
84 | ||
85 | The exception to this idiom is if we’re bringing two items with the same name | |
86 | into scope with `use` statements, because Rust doesn’t allow that. Listing 7-15 | |
87 | shows how to bring two `Result` types into scope that have the same name but | |
88 | different parent modules and how to refer to them. | |
89 | ||
90 | <span class="filename">Filename: src/lib.rs</span> | |
91 | ||
5869c6ff | 92 | ```rust,noplayground |
74b04a01 | 93 | {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-15/src/lib.rs:here}} |
532ac7d7 XL |
94 | ``` |
95 | ||
96 | <span class="caption">Listing 7-15: Bringing two types with the same name into | |
97 | the same scope requires using their parent modules.</span> | |
98 | ||
99 | As you can see, using the parent modules distinguishes the two `Result` types. | |
100 | If instead we specified `use std::fmt::Result` and `use std::io::Result`, we’d | |
101 | have two `Result` types in the same scope and Rust wouldn’t know which one we | |
48663c56 | 102 | meant when we used `Result`. |
532ac7d7 XL |
103 | |
104 | ### Providing New Names with the `as` Keyword | |
105 | ||
106 | There’s another solution to the problem of bringing two types of the same name | |
107 | into the same scope with `use`: after the path, we can specify `as` and a new | |
108 | local name, or alias, for the type. Listing 7-16 shows another way to write the | |
109 | code in Listing 7-15 by renaming one of the two `Result` types using `as`. | |
110 | ||
111 | <span class="filename">Filename: src/lib.rs</span> | |
112 | ||
5869c6ff | 113 | ```rust,noplayground |
74b04a01 | 114 | {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-16/src/lib.rs:here}} |
532ac7d7 XL |
115 | ``` |
116 | ||
117 | <span class="caption">Listing 7-16: Renaming a type when it’s brought into | |
118 | scope with the `as` keyword</span> | |
119 | ||
120 | In the second `use` statement, we chose the new name `IoResult` for the | |
121 | `std::io::Result` type, which won’t conflict with the `Result` from `std::fmt` | |
122 | that we’ve also brought into scope. Listing 7-15 and Listing 7-16 are | |
123 | considered idiomatic, so the choice is up to you! | |
124 | ||
125 | ### Re-exporting Names with `pub use` | |
126 | ||
127 | When we bring a name into scope with the `use` keyword, the name available in | |
128 | the new scope is private. To enable the code that calls our code to refer to | |
129 | that name as if it had been defined in that code’s scope, we can combine `pub` | |
130 | and `use`. This technique is called *re-exporting* because we’re bringing | |
131 | an item into scope but also making that item available for others to bring into | |
132 | their scope. | |
133 | ||
134 | Listing 7-17 shows the code in Listing 7-11 with `use` in the root module | |
135 | changed to `pub use`. | |
136 | ||
137 | <span class="filename">Filename: src/lib.rs</span> | |
138 | ||
fc512014 XL |
139 | ```rust,noplayground,test_harness |
140 | {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-17/src/lib.rs}} | |
532ac7d7 XL |
141 | ``` |
142 | ||
143 | <span class="caption">Listing 7-17: Making a name available for any code to use | |
144 | from a new scope with `pub use`</span> | |
145 | ||
146 | By using `pub use`, external code can now call the `add_to_waitlist` function | |
147 | using `hosting::add_to_waitlist`. If we hadn’t specified `pub use`, the | |
dc9dc135 XL |
148 | `eat_at_restaurant` function could call `hosting::add_to_waitlist` in its |
149 | scope, but external code couldn’t take advantage of this new path. | |
532ac7d7 XL |
150 | |
151 | Re-exporting is useful when the internal structure of your code is different | |
dc9dc135 | 152 | from how programmers calling your code would think about the domain. For |
532ac7d7 XL |
153 | example, in this restaurant metaphor, the people running the restaurant think |
154 | about “front of house” and “back of house.” But customers visiting a restaurant | |
155 | probably won’t think about the parts of the restaurant in those terms. With | |
156 | `pub use`, we can write our code with one structure but expose a different | |
157 | structure. Doing so makes our library well organized for programmers working on | |
158 | the library and programmers calling the library. | |
159 | ||
160 | ### Using External Packages | |
161 | ||
162 | In Chapter 2, we programmed a guessing game project that used an external | |
163 | package called `rand` to get random numbers. To use `rand` in our project, we | |
164 | added this line to *Cargo.toml*: | |
165 | ||
e74abb32 XL |
166 | <!-- When updating the version of `rand` used, also update the version of |
167 | `rand` used in these files so they all match: | |
168 | * ch02-00-guessing-game-tutorial.md | |
169 | * ch14-03-cargo-workspaces.md | |
170 | --> | |
171 | ||
532ac7d7 XL |
172 | <span class="filename">Filename: Cargo.toml</span> |
173 | ||
174 | ```toml | |
74b04a01 | 175 | {{#include ../listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml:9:}} |
532ac7d7 XL |
176 | ``` |
177 | ||
178 | Adding `rand` as a dependency in *Cargo.toml* tells Cargo to download the | |
dc9dc135 XL |
179 | `rand` package and any dependencies from [crates.io](https://crates.io/) and |
180 | make `rand` available to our project. | |
532ac7d7 XL |
181 | |
182 | Then, to bring `rand` definitions into the scope of our package, we added a | |
f035d41b | 183 | `use` line starting with the name of the crate, `rand`, and listed the items |
48663c56 XL |
184 | we wanted to bring into scope. Recall that in the [“Generating a Random |
185 | Number”][rand]<!-- ignore --> section in Chapter 2, we brought the `Rng` trait | |
186 | into scope and called the `rand::thread_rng` function: | |
532ac7d7 XL |
187 | |
188 | ```rust,ignore | |
74b04a01 | 189 | {{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-03/src/main.rs:ch07-04}} |
532ac7d7 XL |
190 | ``` |
191 | ||
192 | Members of the Rust community have made many packages available at | |
dc9dc135 XL |
193 | [crates.io](https://crates.io/), and pulling any of them into your package |
194 | involves these same steps: listing them in your package’s *Cargo.toml* file and | |
f035d41b | 195 | using `use` to bring items from their crates into scope. |
532ac7d7 XL |
196 | |
197 | Note that the standard library (`std`) is also a crate that’s external to our | |
198 | package. Because the standard library is shipped with the Rust language, we | |
199 | don’t need to change *Cargo.toml* to include `std`. But we do need to refer to | |
200 | it with `use` to bring items from there into our package’s scope. For example, | |
201 | with `HashMap` we would use this line: | |
202 | ||
203 | ```rust | |
204 | use std::collections::HashMap; | |
205 | ``` | |
206 | ||
207 | This is an absolute path starting with `std`, the name of the standard library | |
208 | crate. | |
209 | ||
210 | ### Using Nested Paths to Clean Up Large `use` Lists | |
211 | ||
f035d41b | 212 | If we’re using multiple items defined in the same crate or same module, |
532ac7d7 | 213 | listing each item on its own line can take up a lot of vertical space in our |
416331ca XL |
214 | files. For example, these two `use` statements we had in the Guessing Game in |
215 | Listing 2-4 bring items from `std` into scope: | |
532ac7d7 XL |
216 | |
217 | <span class="filename">Filename: src/main.rs</span> | |
218 | ||
74b04a01 XL |
219 | ```rust,ignore |
220 | {{#rustdoc_include ../listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/src/main.rs:here}} | |
532ac7d7 XL |
221 | ``` |
222 | ||
223 | Instead, we can use nested paths to bring the same items into scope in one | |
224 | line. We do this by specifying the common part of the path, followed by two | |
225 | colons, and then curly brackets around a list of the parts of the paths that | |
226 | differ, as shown in Listing 7-18. | |
227 | ||
228 | <span class="filename">Filename: src/main.rs</span> | |
229 | ||
74b04a01 XL |
230 | ```rust,ignore |
231 | {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-18/src/main.rs:here}} | |
532ac7d7 XL |
232 | ``` |
233 | ||
234 | <span class="caption">Listing 7-18: Specifying a nested path to bring multiple | |
235 | items with the same prefix into scope</span> | |
236 | ||
f035d41b | 237 | In bigger programs, bringing many items into scope from the same crate or |
532ac7d7 XL |
238 | module using nested paths can reduce the number of separate `use` statements |
239 | needed by a lot! | |
240 | ||
241 | We can use a nested path at any level in a path, which is useful when combining | |
242 | two `use` statements that share a subpath. For example, Listing 7-19 shows two | |
243 | `use` statements: one that brings `std::io` into scope and one that brings | |
244 | `std::io::Write` into scope. | |
245 | ||
246 | <span class="filename">Filename: src/lib.rs</span> | |
247 | ||
5869c6ff | 248 | ```rust,noplayground |
74b04a01 | 249 | {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-19/src/lib.rs}} |
532ac7d7 XL |
250 | ``` |
251 | ||
252 | <span class="caption">Listing 7-19: Two `use` statements where one is a subpath | |
253 | of the other</span> | |
254 | ||
255 | The common part of these two paths is `std::io`, and that’s the complete first | |
256 | path. To merge these two paths into one `use` statement, we can use `self` in | |
257 | the nested path, as shown in Listing 7-20. | |
258 | ||
259 | <span class="filename">Filename: src/lib.rs</span> | |
260 | ||
5869c6ff | 261 | ```rust,noplayground |
74b04a01 | 262 | {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-20/src/lib.rs}} |
532ac7d7 XL |
263 | ``` |
264 | ||
265 | <span class="caption">Listing 7-20: Combining the paths in Listing 7-19 into | |
266 | one `use` statement</span> | |
267 | ||
268 | This line brings `std::io` and `std::io::Write` into scope. | |
269 | ||
270 | ### The Glob Operator | |
271 | ||
272 | If we want to bring *all* public items defined in a path into scope, we can | |
273 | specify that path followed by `*`, the glob operator: | |
274 | ||
275 | ```rust | |
276 | use std::collections::*; | |
277 | ``` | |
278 | ||
279 | This `use` statement brings all public items defined in `std::collections` into | |
280 | the current scope. Be careful when using the glob operator! Glob can make it | |
281 | harder to tell what names are in scope and where a name used in your program | |
282 | was defined. | |
283 | ||
284 | The glob operator is often used when testing to bring everything under test | |
48663c56 XL |
285 | into the `tests` module; we’ll talk about that in the [“How to Write |
286 | Tests”][writing-tests]<!-- ignore --> section in Chapter 11. The glob operator | |
287 | is also sometimes used as part of the prelude pattern: see [the standard | |
288 | library documentation](../std/prelude/index.html#other-preludes)<!-- ignore --> | |
289 | for more information on that pattern. | |
532ac7d7 XL |
290 | |
291 | [rand]: ch02-00-guessing-game-tutorial.html#generating-a-random-number | |
292 | [writing-tests]: ch11-01-writing-tests.html#how-to-write-tests |