]>
Commit | Line | Data |
---|---|---|
85aaf69f | 1 | % Crates and Modules |
1a4d82fc | 2 | |
bd371182 | 3 | When a project starts getting large, it’s considered good software |
1a4d82fc | 4 | engineering practice to split it up into a bunch of smaller pieces, and then |
9cc50fc6 | 5 | fit them together. It is also important to have a well-defined interface, so |
1a4d82fc JJ |
6 | that some of your functionality is private, and some is public. To facilitate |
7 | these kinds of things, Rust has a module system. | |
8 | ||
9 | # Basic terminology: Crates and Modules | |
10 | ||
bd371182 AL |
11 | Rust has two distinct terms that relate to the module system: ‘crate’ and |
12 | ‘module’. A crate is synonymous with a ‘library’ or ‘package’ in other | |
13 | languages. Hence “Cargo” as the name of Rust’s package management tool: you | |
1a4d82fc | 14 | ship your crates to others with Cargo. Crates can produce an executable or a |
c34b1796 | 15 | library, depending on the project. |
1a4d82fc | 16 | |
85aaf69f | 17 | Each crate has an implicit *root module* that contains the code for that crate. |
1a4d82fc JJ |
18 | You can then define a tree of sub-modules under that root module. Modules allow |
19 | you to partition your code within the crate itself. | |
20 | ||
bd371182 AL |
21 | As an example, let’s make a *phrases* crate, which will give us various phrases |
22 | in different languages. To keep things simple, we’ll stick to ‘greetings’ and | |
23 | ‘farewells’ as two kinds of phrases, and use English and Japanese (日本語) as | |
24 | two languages for those phrases to be in. We’ll use this module layout: | |
5bcae85e | 25 | |
1a4d82fc | 26 | ```text |
c34b1796 AL |
27 | +-----------+ |
28 | +---| greetings | | |
3157f602 | 29 | +---------+ | +-----------+ |
c34b1796 AL |
30 | +---| english |---+ |
31 | | +---------+ | +-----------+ | |
32 | | +---| farewells | | |
33 | +---------+ | +-----------+ | |
1a4d82fc | 34 | | phrases |---+ |
c34b1796 AL |
35 | +---------+ | +-----------+ |
36 | | +---| greetings | | |
37 | | +----------+ | +-----------+ | |
38 | +---| japanese |--+ | |
3157f602 | 39 | +----------+ | +-----------+ |
c34b1796 AL |
40 | +---| farewells | |
41 | +-----------+ | |
1a4d82fc JJ |
42 | ``` |
43 | ||
44 | In this example, `phrases` is the name of our crate. All of the rest are | |
45 | modules. You can see that they form a tree, branching out from the crate | |
85aaf69f | 46 | *root*, which is the root of the tree: `phrases` itself. |
1a4d82fc | 47 | |
bd371182 | 48 | Now that we have a plan, let’s define these modules in code. To start, |
1a4d82fc JJ |
49 | generate a new crate with Cargo: |
50 | ||
51 | ```bash | |
52 | $ cargo new phrases | |
53 | $ cd phrases | |
54 | ``` | |
55 | ||
56 | If you remember, this generates a simple project for us: | |
57 | ||
58 | ```bash | |
59 | $ tree . | |
60 | . | |
61 | ├── Cargo.toml | |
62 | └── src | |
63 | └── lib.rs | |
64 | ||
65 | 1 directory, 2 files | |
66 | ``` | |
67 | ||
68 | `src/lib.rs` is our crate root, corresponding to the `phrases` in our diagram | |
69 | above. | |
70 | ||
71 | # Defining Modules | |
72 | ||
bd371182 | 73 | To define each of our modules, we use the `mod` keyword. Let’s make our |
1a4d82fc JJ |
74 | `src/lib.rs` look like this: |
75 | ||
62682a34 | 76 | ```rust |
1a4d82fc JJ |
77 | mod english { |
78 | mod greetings { | |
1a4d82fc JJ |
79 | } |
80 | ||
81 | mod farewells { | |
1a4d82fc JJ |
82 | } |
83 | } | |
84 | ||
85 | mod japanese { | |
86 | mod greetings { | |
1a4d82fc JJ |
87 | } |
88 | ||
89 | mod farewells { | |
1a4d82fc JJ |
90 | } |
91 | } | |
92 | ``` | |
93 | ||
94 | After the `mod` keyword, you give the name of the module. Module names follow | |
95 | the conventions for other Rust identifiers: `lower_snake_case`. The contents of | |
96 | each module are within curly braces (`{}`). | |
97 | ||
98 | Within a given `mod`, you can declare sub-`mod`s. We can refer to sub-modules | |
99 | with double-colon (`::`) notation: our four nested modules are | |
100 | `english::greetings`, `english::farewells`, `japanese::greetings`, and | |
101 | `japanese::farewells`. Because these sub-modules are namespaced under their | |
bd371182 | 102 | parent module, the names don’t conflict: `english::greetings` and |
1a4d82fc JJ |
103 | `japanese::greetings` are distinct, even though their names are both |
104 | `greetings`. | |
105 | ||
106 | Because this crate does not have a `main()` function, and is called `lib.rs`, | |
107 | Cargo will build this crate as a library: | |
108 | ||
109 | ```bash | |
110 | $ cargo build | |
111 | Compiling phrases v0.0.1 (file:///home/you/projects/phrases) | |
9346a6ac AL |
112 | $ ls target/debug |
113 | build deps examples libphrases-a7448e02a0468eaa.rlib native | |
1a4d82fc JJ |
114 | ``` |
115 | ||
a7813a04 | 116 | `libphrases-<hash>.rlib` is the compiled crate. Before we see how to use this |
bd371182 | 117 | crate from another crate, let’s break it up into multiple files. |
1a4d82fc | 118 | |
54a0048b | 119 | # Multiple File Crates |
1a4d82fc | 120 | |
bd371182 | 121 | If each crate were just one file, these files would get very large. It’s often |
1a4d82fc JJ |
122 | easier to split up crates into multiple files, and Rust supports this in two |
123 | ways. | |
124 | ||
125 | Instead of declaring a module like this: | |
126 | ||
62682a34 | 127 | ```rust,ignore |
1a4d82fc JJ |
128 | mod english { |
129 | // contents of our module go here | |
130 | } | |
131 | ``` | |
132 | ||
133 | We can instead declare our module like this: | |
134 | ||
62682a34 | 135 | ```rust,ignore |
1a4d82fc JJ |
136 | mod english; |
137 | ``` | |
138 | ||
139 | If we do that, Rust will expect to find either a `english.rs` file, or a | |
c34b1796 | 140 | `english/mod.rs` file with the contents of our module. |
1a4d82fc | 141 | |
bd371182 | 142 | Note that in these files, you don’t need to re-declare the module: that’s |
1a4d82fc JJ |
143 | already been done with the initial `mod` declaration. |
144 | ||
145 | Using these two techniques, we can break up our crate into two directories and | |
146 | seven files: | |
147 | ||
148 | ```bash | |
149 | $ tree . | |
150 | . | |
151 | ├── Cargo.lock | |
152 | ├── Cargo.toml | |
153 | ├── src | |
154 | │ ├── english | |
155 | │ │ ├── farewells.rs | |
156 | │ │ ├── greetings.rs | |
157 | │ │ └── mod.rs | |
158 | │ ├── japanese | |
159 | │ │ ├── farewells.rs | |
160 | │ │ ├── greetings.rs | |
161 | │ │ └── mod.rs | |
162 | │ └── lib.rs | |
163 | └── target | |
9346a6ac AL |
164 | └── debug |
165 | ├── build | |
166 | ├── deps | |
167 | ├── examples | |
168 | ├── libphrases-a7448e02a0468eaa.rlib | |
169 | └── native | |
1a4d82fc JJ |
170 | ``` |
171 | ||
172 | `src/lib.rs` is our crate root, and looks like this: | |
173 | ||
62682a34 | 174 | ```rust,ignore |
1a4d82fc | 175 | mod english; |
1a4d82fc JJ |
176 | mod japanese; |
177 | ``` | |
178 | ||
179 | These two declarations tell Rust to look for either `src/english.rs` and | |
180 | `src/japanese.rs`, or `src/english/mod.rs` and `src/japanese/mod.rs`, depending | |
bd371182 | 181 | on our preference. In this case, because our modules have sub-modules, we’ve |
1a4d82fc JJ |
182 | chosen the second. Both `src/english/mod.rs` and `src/japanese/mod.rs` look |
183 | like this: | |
184 | ||
62682a34 | 185 | ```rust,ignore |
1a4d82fc | 186 | mod greetings; |
1a4d82fc JJ |
187 | mod farewells; |
188 | ``` | |
189 | ||
190 | Again, these declarations tell Rust to look for either | |
54a0048b SL |
191 | `src/english/greetings.rs`, `src/english/farewells.rs`, |
192 | `src/japanese/greetings.rs` and `src/japanese/farewells.rs` or | |
193 | `src/english/greetings/mod.rs`, `src/english/farewells/mod.rs`, | |
194 | `src/japanese/greetings/mod.rs` and | |
195 | `src/japanese/farewells/mod.rs`. Because these sub-modules don’t have | |
196 | their own sub-modules, we’ve chosen to make them | |
197 | `src/english/greetings.rs`, `src/english/farewells.rs`, | |
198 | `src/japanese/greetings.rs` and `src/japanese/farewells.rs`. Whew! | |
199 | ||
200 | The contents of `src/english/greetings.rs`, | |
201 | `src/english/farewells.rs`, `src/japanese/greetings.rs` and | |
202 | `src/japanese/farewells.rs` are all empty at the moment. Let’s add | |
203 | some functions. | |
1a4d82fc JJ |
204 | |
205 | Put this in `src/english/greetings.rs`: | |
206 | ||
207 | ```rust | |
1a4d82fc JJ |
208 | fn hello() -> String { |
209 | "Hello!".to_string() | |
210 | } | |
211 | ``` | |
212 | ||
213 | Put this in `src/english/farewells.rs`: | |
214 | ||
215 | ```rust | |
1a4d82fc JJ |
216 | fn goodbye() -> String { |
217 | "Goodbye.".to_string() | |
218 | } | |
219 | ``` | |
220 | ||
221 | Put this in `src/japanese/greetings.rs`: | |
222 | ||
223 | ```rust | |
1a4d82fc JJ |
224 | fn hello() -> String { |
225 | "こんにちは".to_string() | |
226 | } | |
227 | ``` | |
228 | ||
9cc50fc6 | 229 | Of course, you can copy and paste this from this web page, or type |
bd371182 | 230 | something else. It’s not important that you actually put ‘konnichiwa’ to learn |
1a4d82fc JJ |
231 | about the module system. |
232 | ||
233 | Put this in `src/japanese/farewells.rs`: | |
234 | ||
235 | ```rust | |
1a4d82fc JJ |
236 | fn goodbye() -> String { |
237 | "さようなら".to_string() | |
238 | } | |
239 | ``` | |
240 | ||
bd371182 | 241 | (This is ‘Sayōnara’, if you’re curious.) |
1a4d82fc | 242 | |
bd371182 | 243 | Now that we have some functionality in our crate, let’s try to use it from |
1a4d82fc JJ |
244 | another crate. |
245 | ||
246 | # Importing External Crates | |
247 | ||
bd371182 | 248 | We have a library crate. Let’s make an executable crate that imports and uses |
1a4d82fc JJ |
249 | our library. |
250 | ||
bd371182 | 251 | Make a `src/main.rs` and put this in it (it won’t quite compile yet): |
1a4d82fc JJ |
252 | |
253 | ```rust,ignore | |
1a4d82fc JJ |
254 | extern crate phrases; |
255 | ||
256 | fn main() { | |
257 | println!("Hello in English: {}", phrases::english::greetings::hello()); | |
258 | println!("Goodbye in English: {}", phrases::english::farewells::goodbye()); | |
259 | ||
260 | println!("Hello in Japanese: {}", phrases::japanese::greetings::hello()); | |
261 | println!("Goodbye in Japanese: {}", phrases::japanese::farewells::goodbye()); | |
262 | } | |
263 | ``` | |
264 | ||
265 | The `extern crate` declaration tells Rust that we need to compile and link to | |
bd371182 | 266 | the `phrases` crate. We can then use `phrases`’ modules in this one. As we |
1a4d82fc JJ |
267 | mentioned earlier, you can use double colons to refer to sub-modules and the |
268 | functions inside of them. | |
269 | ||
e9174d1e SL |
270 | (Note: when importing a crate that has dashes in its name "like-this", which is |
271 | not a valid Rust identifier, it will be converted by changing the dashes to | |
272 | underscores, so you would write `extern crate like_this;`.) | |
273 | ||
1a4d82fc | 274 | Also, Cargo assumes that `src/main.rs` is the crate root of a binary crate, |
85aaf69f | 275 | rather than a library crate. Our package now has two crates: `src/lib.rs` and |
1a4d82fc JJ |
276 | `src/main.rs`. This pattern is quite common for executable crates: most |
277 | functionality is in a library crate, and the executable crate uses that | |
bd371182 | 278 | library. This way, other programs can also use the library crate, and it’s also |
1a4d82fc JJ |
279 | a nice separation of concerns. |
280 | ||
bd371182 | 281 | This doesn’t quite work yet, though. We get four errors that look similar to |
1a4d82fc JJ |
282 | this: |
283 | ||
284 | ```bash | |
285 | $ cargo build | |
286 | Compiling phrases v0.0.1 (file:///home/you/projects/phrases) | |
9346a6ac AL |
287 | src/main.rs:4:38: 4:72 error: function `hello` is private |
288 | src/main.rs:4 println!("Hello in English: {}", phrases::english::greetings::hello()); | |
289 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
1a4d82fc | 290 | note: in expansion of format_args! |
9346a6ac AL |
291 | <std macros>:2:25: 2:58 note: expansion site |
292 | <std macros>:1:1: 2:62 note: in expansion of print! | |
293 | <std macros>:3:1: 3:54 note: expansion site | |
294 | <std macros>:1:1: 3:58 note: in expansion of println! | |
295 | phrases/src/main.rs:4:5: 4:76 note: expansion site | |
1a4d82fc JJ |
296 | ``` |
297 | ||
bd371182 | 298 | By default, everything is private in Rust. Let’s talk about this in some more |
1a4d82fc JJ |
299 | depth. |
300 | ||
301 | # Exporting a Public Interface | |
302 | ||
303 | Rust allows you to precisely control which aspects of your interface are | |
304 | public, and so private is the default. To make things public, you use the `pub` | |
bd371182 | 305 | keyword. Let’s focus on the `english` module first, so let’s reduce our `src/main.rs` |
9cc50fc6 | 306 | to only this: |
1a4d82fc | 307 | |
62682a34 | 308 | ```rust,ignore |
1a4d82fc JJ |
309 | extern crate phrases; |
310 | ||
311 | fn main() { | |
312 | println!("Hello in English: {}", phrases::english::greetings::hello()); | |
313 | println!("Goodbye in English: {}", phrases::english::farewells::goodbye()); | |
314 | } | |
315 | ``` | |
316 | ||
bd371182 | 317 | In our `src/lib.rs`, let’s add `pub` to the `english` module declaration: |
1a4d82fc | 318 | |
62682a34 | 319 | ```rust,ignore |
1a4d82fc | 320 | pub mod english; |
1a4d82fc JJ |
321 | mod japanese; |
322 | ``` | |
323 | ||
bd371182 | 324 | And in our `src/english/mod.rs`, let’s make both `pub`: |
1a4d82fc | 325 | |
62682a34 | 326 | ```rust,ignore |
1a4d82fc | 327 | pub mod greetings; |
1a4d82fc JJ |
328 | pub mod farewells; |
329 | ``` | |
330 | ||
bd371182 | 331 | In our `src/english/greetings.rs`, let’s add `pub` to our `fn` declaration: |
1a4d82fc | 332 | |
62682a34 | 333 | ```rust,ignore |
1a4d82fc JJ |
334 | pub fn hello() -> String { |
335 | "Hello!".to_string() | |
336 | } | |
337 | ``` | |
338 | ||
339 | And also in `src/english/farewells.rs`: | |
340 | ||
62682a34 | 341 | ```rust,ignore |
1a4d82fc JJ |
342 | pub fn goodbye() -> String { |
343 | "Goodbye.".to_string() | |
344 | } | |
345 | ``` | |
346 | ||
347 | Now, our crate compiles, albeit with warnings about not using the `japanese` | |
348 | functions: | |
349 | ||
350 | ```bash | |
351 | $ cargo run | |
352 | Compiling phrases v0.0.1 (file:///home/you/projects/phrases) | |
9346a6ac AL |
353 | src/japanese/greetings.rs:1:1: 3:2 warning: function is never used: `hello`, #[warn(dead_code)] on by default |
354 | src/japanese/greetings.rs:1 fn hello() -> String { | |
355 | src/japanese/greetings.rs:2 "こんにちは".to_string() | |
356 | src/japanese/greetings.rs:3 } | |
357 | src/japanese/farewells.rs:1:1: 3:2 warning: function is never used: `goodbye`, #[warn(dead_code)] on by default | |
358 | src/japanese/farewells.rs:1 fn goodbye() -> String { | |
359 | src/japanese/farewells.rs:2 "さようなら".to_string() | |
360 | src/japanese/farewells.rs:3 } | |
361 | Running `target/debug/phrases` | |
1a4d82fc JJ |
362 | Hello in English: Hello! |
363 | Goodbye in English: Goodbye. | |
364 | ``` | |
365 | ||
c1a9b12d SL |
366 | `pub` also applies to `struct`s and their member fields. In keeping with Rust’s |
367 | tendency toward safety, simply making a `struct` public won't automatically | |
368 | make its members public: you must mark the fields individually with `pub`. | |
369 | ||
1a4d82fc JJ |
370 | Now that our functions are public, we can use them. Great! However, typing out |
371 | `phrases::english::greetings::hello()` is very long and repetitive. Rust has | |
372 | another keyword for importing names into the current scope, so that you can | |
bd371182 | 373 | refer to them with shorter names. Let’s talk about `use`. |
1a4d82fc JJ |
374 | |
375 | # Importing Modules with `use` | |
376 | ||
377 | Rust has a `use` keyword, which allows us to import names into our local scope. | |
bd371182 | 378 | Let’s change our `src/main.rs` to look like this: |
1a4d82fc | 379 | |
62682a34 | 380 | ```rust,ignore |
1a4d82fc JJ |
381 | extern crate phrases; |
382 | ||
383 | use phrases::english::greetings; | |
384 | use phrases::english::farewells; | |
385 | ||
386 | fn main() { | |
387 | println!("Hello in English: {}", greetings::hello()); | |
388 | println!("Goodbye in English: {}", farewells::goodbye()); | |
389 | } | |
390 | ``` | |
391 | ||
392 | The two `use` lines import each module into the local scope, so we can refer to | |
bd371182 | 393 | the functions by a much shorter name. By convention, when importing functions, it’s |
1a4d82fc JJ |
394 | considered best practice to import the module, rather than the function directly. In |
395 | other words, you _can_ do this: | |
396 | ||
62682a34 | 397 | ```rust,ignore |
1a4d82fc JJ |
398 | extern crate phrases; |
399 | ||
400 | use phrases::english::greetings::hello; | |
401 | use phrases::english::farewells::goodbye; | |
402 | ||
403 | fn main() { | |
404 | println!("Hello in English: {}", hello()); | |
405 | println!("Goodbye in English: {}", goodbye()); | |
406 | } | |
407 | ``` | |
408 | ||
c34b1796 | 409 | But it is not idiomatic. This is significantly more likely to introduce a |
bd371182 | 410 | naming conflict. In our short program, it’s not a big deal, but as it grows, it |
1a4d82fc JJ |
411 | becomes a problem. If we have conflicting names, Rust will give a compilation |
412 | error. For example, if we made the `japanese` functions public, and tried to do | |
413 | this: | |
414 | ||
62682a34 | 415 | ```rust,ignore |
1a4d82fc JJ |
416 | extern crate phrases; |
417 | ||
418 | use phrases::english::greetings::hello; | |
419 | use phrases::japanese::greetings::hello; | |
420 | ||
421 | fn main() { | |
422 | println!("Hello in English: {}", hello()); | |
423 | println!("Hello in Japanese: {}", hello()); | |
424 | } | |
425 | ``` | |
426 | ||
427 | Rust will give us a compile-time error: | |
428 | ||
429 | ```text | |
430 | Compiling phrases v0.0.1 (file:///home/you/projects/phrases) | |
9346a6ac AL |
431 | src/main.rs:4:5: 4:40 error: a value named `hello` has already been imported in this module [E0252] |
432 | src/main.rs:4 use phrases::japanese::greetings::hello; | |
433 | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
1a4d82fc JJ |
434 | error: aborting due to previous error |
435 | Could not compile `phrases`. | |
436 | ``` | |
437 | ||
bd371182 | 438 | If we’re importing multiple names from the same module, we don’t have to type it out |
c34b1796 | 439 | twice. Instead of this: |
1a4d82fc | 440 | |
62682a34 | 441 | ```rust,ignore |
1a4d82fc JJ |
442 | use phrases::english::greetings; |
443 | use phrases::english::farewells; | |
444 | ``` | |
445 | ||
c34b1796 | 446 | We can use this shortcut: |
1a4d82fc | 447 | |
62682a34 | 448 | ```rust,ignore |
1a4d82fc JJ |
449 | use phrases::english::{greetings, farewells}; |
450 | ``` | |
451 | ||
1a4d82fc JJ |
452 | ## Re-exporting with `pub use` |
453 | ||
9cc50fc6 | 454 | You don’t only use `use` to shorten identifiers. You can also use it inside of your crate |
1a4d82fc JJ |
455 | to re-export a function inside another module. This allows you to present an external |
456 | interface that may not directly map to your internal code organization. | |
457 | ||
bd371182 | 458 | Let’s look at an example. Modify your `src/main.rs` to read like this: |
1a4d82fc | 459 | |
62682a34 | 460 | ```rust,ignore |
1a4d82fc JJ |
461 | extern crate phrases; |
462 | ||
463 | use phrases::english::{greetings,farewells}; | |
464 | use phrases::japanese; | |
465 | ||
466 | fn main() { | |
467 | println!("Hello in English: {}", greetings::hello()); | |
468 | println!("Goodbye in English: {}", farewells::goodbye()); | |
469 | ||
470 | println!("Hello in Japanese: {}", japanese::hello()); | |
471 | println!("Goodbye in Japanese: {}", japanese::goodbye()); | |
472 | } | |
473 | ``` | |
474 | ||
475 | Then, modify your `src/lib.rs` to make the `japanese` mod public: | |
476 | ||
62682a34 | 477 | ```rust,ignore |
1a4d82fc | 478 | pub mod english; |
1a4d82fc JJ |
479 | pub mod japanese; |
480 | ``` | |
481 | ||
482 | Next, make the two functions public, first in `src/japanese/greetings.rs`: | |
483 | ||
62682a34 | 484 | ```rust,ignore |
1a4d82fc JJ |
485 | pub fn hello() -> String { |
486 | "こんにちは".to_string() | |
487 | } | |
488 | ``` | |
489 | ||
490 | And then in `src/japanese/farewells.rs`: | |
491 | ||
62682a34 | 492 | ```rust,ignore |
1a4d82fc JJ |
493 | pub fn goodbye() -> String { |
494 | "さようなら".to_string() | |
495 | } | |
496 | ``` | |
497 | ||
498 | Finally, modify your `src/japanese/mod.rs` to read like this: | |
499 | ||
62682a34 | 500 | ```rust,ignore |
1a4d82fc JJ |
501 | pub use self::greetings::hello; |
502 | pub use self::farewells::goodbye; | |
503 | ||
504 | mod greetings; | |
1a4d82fc JJ |
505 | mod farewells; |
506 | ``` | |
507 | ||
508 | The `pub use` declaration brings the function into scope at this part of our | |
bd371182 | 509 | module hierarchy. Because we’ve `pub use`d this inside of our `japanese` |
1a4d82fc JJ |
510 | module, we now have a `phrases::japanese::hello()` function and a |
511 | `phrases::japanese::goodbye()` function, even though the code for them lives in | |
512 | `phrases::japanese::greetings::hello()` and | |
bd371182 | 513 | `phrases::japanese::farewells::goodbye()`. Our internal organization doesn’t |
1a4d82fc JJ |
514 | define our external interface. |
515 | ||
c34b1796 | 516 | Here we have a `pub use` for each function we want to bring into the |
85aaf69f | 517 | `japanese` scope. We could alternatively use the wildcard syntax to include |
c34b1796 AL |
518 | everything from `greetings` into the current scope: `pub use self::greetings::*`. |
519 | ||
520 | What about the `self`? Well, by default, `use` declarations are absolute paths, | |
521 | starting from your crate root. `self` makes that path relative to your current | |
bd371182 | 522 | place in the hierarchy instead. There’s one more special form of `use`: you can |
c34b1796 | 523 | `use super::` to reach one level up the tree from your current location. Some |
bd371182 | 524 | people like to think of `self` as `.` and `super` as `..`, from many shells’ |
c34b1796 AL |
525 | display for the current directory and the parent directory. |
526 | ||
527 | Outside of `use`, paths are relative: `foo::bar()` refers to a function inside | |
bd371182 | 528 | of `foo` relative to where we are. If that’s prefixed with `::`, as in |
c34b1796 AL |
529 | `::foo::bar()`, it refers to a different `foo`, an absolute path from your |
530 | crate root. | |
85aaf69f | 531 | |
1a4d82fc JJ |
532 | This will build and run: |
533 | ||
534 | ```bash | |
85aaf69f | 535 | $ cargo run |
1a4d82fc | 536 | Compiling phrases v0.0.1 (file:///home/you/projects/phrases) |
9346a6ac | 537 | Running `target/debug/phrases` |
1a4d82fc JJ |
538 | Hello in English: Hello! |
539 | Goodbye in English: Goodbye. | |
540 | Hello in Japanese: こんにちは | |
541 | Goodbye in Japanese: さようなら | |
542 | ``` | |
e9174d1e SL |
543 | |
544 | ## Complex imports | |
545 | ||
546 | Rust offers several advanced options that can add compactness and | |
547 | convenience to your `extern crate` and `use` statements. Here is an example: | |
548 | ||
549 | ```rust,ignore | |
550 | extern crate phrases as sayings; | |
551 | ||
552 | use sayings::japanese::greetings as ja_greetings; | |
553 | use sayings::japanese::farewells::*; | |
554 | use sayings::english::{self, greetings as en_greetings, farewells as en_farewells}; | |
555 | ||
556 | fn main() { | |
557 | println!("Hello in English; {}", en_greetings::hello()); | |
558 | println!("And in Japanese: {}", ja_greetings::hello()); | |
559 | println!("Goodbye in English: {}", english::farewells::goodbye()); | |
560 | println!("Again: {}", en_farewells::goodbye()); | |
561 | println!("And in Japanese: {}", goodbye()); | |
562 | } | |
563 | ``` | |
564 | ||
565 | What's going on here? | |
566 | ||
567 | First, both `extern crate` and `use` allow renaming the thing that is being | |
568 | imported. So the crate is still called "phrases", but here we will refer | |
569 | to it as "sayings". Similarly, the first `use` statement pulls in the | |
b039eaaf SL |
570 | `japanese::greetings` module from the crate, but makes it available as |
571 | `ja_greetings` as opposed to simply `greetings`. This can help to avoid | |
e9174d1e SL |
572 | ambiguity when importing similarly-named items from different places. |
573 | ||
7453a54e SL |
574 | The second `use` statement uses a star glob to bring in all public symbols from |
575 | the `sayings::japanese::farewells` module. As you can see we can later refer to | |
e9174d1e | 576 | the Japanese `goodbye` function with no module qualifiers. This kind of glob |
7453a54e SL |
577 | should be used sparingly. It’s worth noting that it only imports the public |
578 | symbols, even if the code doing the globbing is in the same module. | |
e9174d1e SL |
579 | |
580 | The third `use` statement bears more explanation. It's using "brace expansion" | |
581 | globbing to compress three `use` statements into one (this sort of syntax | |
582 | may be familiar if you've written Linux shell scripts before). The | |
583 | uncompressed form of this statement would be: | |
b039eaaf | 584 | |
e9174d1e SL |
585 | ```rust,ignore |
586 | use sayings::english; | |
587 | use sayings::english::greetings as en_greetings; | |
588 | use sayings::english::farewells as en_farewells; | |
589 | ``` | |
b039eaaf | 590 | |
e9174d1e | 591 | As you can see, the curly brackets compress `use` statements for several items |
9cc50fc6 | 592 | under the same path, and in this context `self` refers back to that path. |
e9174d1e | 593 | Note: The curly brackets cannot be nested or mixed with star globbing. |