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