3 When a project starts getting large, it's considered a good software
4 engineering practice to split it up into a bunch of smaller pieces, and then
5 fit them together. It's also important to have a well-defined interface, so
6 that some of your functionality is private, and some is public. To facilitate
7 these kinds of things, Rust has a module system.
9 # Basic terminology: Crates and Modules
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
14 ship your crates to others with Cargo. Crates can produce an executable or a
15 shared library, depending on the project.
17 Each crate has an implicit *root module* that contains the code for that crate.
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.
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:
32 +---------+ | +-----------+
34 +---------+ | +-----------+
36 +---------+ | +-----------+
38 +----------+ | +-----------+
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
48 *root*, which is the root of the tree: `phrases` itself.
50 Now that we have a plan, let's define these modules in code. To start,
51 generate a new crate with Cargo:
58 If you remember, this generates a simple project for us:
70 `src/lib.rs` is our crate root, corresponding to the `phrases` in our diagram
75 To define each of our modules, we use the `mod` keyword. Let's make our
76 `src/lib.rs` look like this:
102 After the `mod` keyword, you give the name of the module. Module names follow
103 the conventions for other Rust identifiers: `lower_snake_case`. The contents of
104 each module are within curly braces (`{}`).
106 Within a given `mod`, you can declare sub-`mod`s. We can refer to sub-modules
107 with double-colon (`::`) notation: our four nested modules are
108 `english::greetings`, `english::farewells`, `japanese::greetings`, and
109 `japanese::farewells`. Because these sub-modules are namespaced under their
110 parent module, the names don't conflict: `english::greetings` and
111 `japanese::greetings` are distinct, even though their names are both
114 Because this crate does not have a `main()` function, and is called `lib.rs`,
115 Cargo will build this crate as a library:
119 Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
121 deps libphrases-a7448e02a0468eaa.rlib native
124 `libphrase-hash.rlib` is the compiled crate. Before we see how to use this
125 crate from another crate, let's break it up into multiple files.
127 # Multiple file crates
129 If each crate were just one file, these files would get very large. It's often
130 easier to split up crates into multiple files, and Rust supports this in two
133 Instead of declaring a module like this:
137 // contents of our module go here
141 We can instead declare our module like this:
147 If we do that, Rust will expect to find either a `english.rs` file, or a
148 `english/mod.rs` file with the contents of our module:
151 // contents of our module go here
154 Note that in these files, you don't need to re-declare the module: that's
155 already been done with the initial `mod` declaration.
157 Using these two techniques, we can break up our crate into two directories and
177 ├── libphrases-a7448e02a0468eaa.rlib
181 `src/lib.rs` is our crate root, and looks like this:
191 These two declarations tell Rust to look for either `src/english.rs` and
192 `src/japanese.rs`, or `src/english/mod.rs` and `src/japanese/mod.rs`, depending
193 on our preference. In this case, because our modules have sub-modules, we've
194 chosen the second. Both `src/english/mod.rs` and `src/japanese/mod.rs` look
198 // both src/english/mod.rs and src/japanese/mod.rs
205 Again, these declarations tell Rust to look for either
206 `src/english/greetings.rs` and `src/japanese/greetings.rs` or
207 `src/english/farewells/mod.rs` and `src/japanese/farewells/mod.rs`. Because
208 these sub-modules don't have their own sub-modules, we've chosen to make them
209 `src/english/greetings.rs` and `src/japanese/farewells.rs`. Whew!
211 The contents of `src/english/greetings.rs` and `src/japanese/farewells.rs` are
212 both empty at the moment. Let's add some functions.
214 Put this in `src/english/greetings.rs`:
217 // in src/english/greetings.rs
219 fn hello() -> String {
224 Put this in `src/english/farewells.rs`:
227 // in src/english/farewells.rs
229 fn goodbye() -> String {
230 "Goodbye.".to_string()
234 Put this in `src/japanese/greetings.rs`:
237 // in src/japanese/greetings.rs
239 fn hello() -> String {
244 Of course, you can copy and paste this from this web page, or just type
245 something else. It's not important that you actually put "konnichiwa" to learn
246 about the module system.
248 Put this in `src/japanese/farewells.rs`:
251 // in src/japanese/farewells.rs
253 fn goodbye() -> String {
258 (This is "Sayōnara", if you're curious.)
260 Now that we have our some functionality in our crate, let's try to use it from
263 # Importing External Crates
265 We have a library crate. Let's make an executable crate that imports and uses
268 Make a `src/main.rs` and put this in it: (it won't quite compile yet)
273 extern crate phrases;
276 println!("Hello in English: {}", phrases::english::greetings::hello());
277 println!("Goodbye in English: {}", phrases::english::farewells::goodbye());
279 println!("Hello in Japanese: {}", phrases::japanese::greetings::hello());
280 println!("Goodbye in Japanese: {}", phrases::japanese::farewells::goodbye());
284 The `extern crate` declaration tells Rust that we need to compile and link to
285 the `phrases` crate. We can then use `phrases`' modules in this one. As we
286 mentioned earlier, you can use double colons to refer to sub-modules and the
287 functions inside of them.
289 Also, Cargo assumes that `src/main.rs` is the crate root of a binary crate,
290 rather than a library crate. Once we compile `src/main.rs`, we'll get an
291 executable that we can run. Our package now has two crates: `src/lib.rs` and
292 `src/main.rs`. This pattern is quite common for executable crates: most
293 functionality is in a library crate, and the executable crate uses that
294 library. This way, other programs can also use the library crate, and it's also
295 a nice separation of concerns.
297 This doesn't quite work yet, though. We get four errors that look similar to
302 Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
303 /home/you/projects/phrases/src/main.rs:4:38: 4:72 error: function `hello` is private
304 /home/you/projects/phrases/src/main.rs:4 println!("Hello in English: {}", phrases::english::greetings::hello());
305 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
306 note: in expansion of format_args!
307 <std macros>:2:23: 2:77 note: expansion site
308 <std macros>:1:1: 3:2 note: in expansion of println!
309 /home/you/projects/phrases/src/main.rs:4:5: 4:76 note: expansion site
313 By default, everything is private in Rust. Let's talk about this in some more
316 # Exporting a Public Interface
318 Rust allows you to precisely control which aspects of your interface are
319 public, and so private is the default. To make things public, you use the `pub`
320 keyword. Let's focus on the `english` module first, so let's reduce our `src/main.rs`
326 extern crate phrases;
329 println!("Hello in English: {}", phrases::english::greetings::hello());
330 println!("Goodbye in English: {}", phrases::english::farewells::goodbye());
334 In our `src/lib.rs`, let's add `pub` to the `english` module declaration:
344 And in our `src/english/mod.rs`, let's make both `pub`:
347 // in src/english/mod.rs
354 In our `src/english/greetings.rs`, let's add `pub` to our `fn` declaration:
357 // in src/english/greetings.rs
359 pub fn hello() -> String {
364 And also in `src/english/farewells.rs`:
367 // in src/english/farewells.rs
369 pub fn goodbye() -> String {
370 "Goodbye.".to_string()
374 Now, our crate compiles, albeit with warnings about not using the `japanese`
379 Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
380 /home/you/projects/phrases/src/japanese/greetings.rs:1:1: 3:2 warning: code is never used: `hello`, #[warn(dead_code)] on by default
381 /home/you/projects/phrases/src/japanese/greetings.rs:1 fn hello() -> String {
382 /home/you/projects/phrases/src/japanese/greetings.rs:2 "こんにちは".to_string()
383 /home/you/projects/phrases/src/japanese/greetings.rs:3 }
384 /home/you/projects/phrases/src/japanese/farewells.rs:1:1: 3:2 warning: code is never used: `goodbye`, #[warn(dead_code)] on by default
385 /home/you/projects/phrases/src/japanese/farewells.rs:1 fn goodbye() -> String {
386 /home/you/projects/phrases/src/japanese/farewells.rs:2 "さようなら".to_string()
387 /home/you/projects/phrases/src/japanese/farewells.rs:3 }
388 Running `target/phrases`
389 Hello in English: Hello!
390 Goodbye in English: Goodbye.
393 Now that our functions are public, we can use them. Great! However, typing out
394 `phrases::english::greetings::hello()` is very long and repetitive. Rust has
395 another keyword for importing names into the current scope, so that you can
396 refer to them with shorter names. Let's talk about `use`.
398 # Importing Modules with `use`
400 Rust has a `use` keyword, which allows us to import names into our local scope.
401 Let's change our `src/main.rs` to look like this:
406 extern crate phrases;
408 use phrases::english::greetings;
409 use phrases::english::farewells;
412 println!("Hello in English: {}", greetings::hello());
413 println!("Goodbye in English: {}", farewells::goodbye());
417 The two `use` lines import each module into the local scope, so we can refer to
418 the functions by a much shorter name. By convention, when importing functions, it's
419 considered best practice to import the module, rather than the function directly. In
420 other words, you _can_ do this:
423 extern crate phrases;
425 use phrases::english::greetings::hello;
426 use phrases::english::farewells::goodbye;
429 println!("Hello in English: {}", hello());
430 println!("Goodbye in English: {}", goodbye());
434 But it is not idiomatic. This is significantly more likely to introducing a
435 naming conflict. In our short program, it's not a big deal, but as it grows, it
436 becomes a problem. If we have conflicting names, Rust will give a compilation
437 error. For example, if we made the `japanese` functions public, and tried to do
441 extern crate phrases;
443 use phrases::english::greetings::hello;
444 use phrases::japanese::greetings::hello;
447 println!("Hello in English: {}", hello());
448 println!("Hello in Japanese: {}", hello());
452 Rust will give us a compile-time error:
455 Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
456 /home/you/projects/phrases/src/main.rs:4:5: 4:40 error: a value named `hello` has already been imported in this module
457 /home/you/projects/phrases/src/main.rs:4 use phrases::japanese::greetings::hello;
458 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
459 error: aborting due to previous error
460 Could not compile `phrases`.
463 If we're importing multiple names from the same module, we don't have to type it out
464 twice. Rust has a shortcut syntax for writing this:
467 use phrases::english::greetings;
468 use phrases::english::farewells;
471 You use curly braces:
474 use phrases::english::{greetings, farewells};
477 These two declarations are equivalent, but the second is a lot less typing.
479 ## Re-exporting with `pub use`
481 You don't just use `use` to shorten identifiers. You can also use it inside of your crate
482 to re-export a function inside another module. This allows you to present an external
483 interface that may not directly map to your internal code organization.
485 Let's look at an example. Modify your `src/main.rs` to read like this:
490 extern crate phrases;
492 use phrases::english::{greetings,farewells};
493 use phrases::japanese;
496 println!("Hello in English: {}", greetings::hello());
497 println!("Goodbye in English: {}", farewells::goodbye());
499 println!("Hello in Japanese: {}", japanese::hello());
500 println!("Goodbye in Japanese: {}", japanese::goodbye());
504 Then, modify your `src/lib.rs` to make the `japanese` mod public:
514 Next, make the two functions public, first in `src/japanese/greetings.rs`:
517 // in src/japanese/greetings.rs
519 pub fn hello() -> String {
524 And then in `src/japanese/farewells.rs`:
527 // in src/japanese/farewells.rs
529 pub fn goodbye() -> String {
534 Finally, modify your `src/japanese/mod.rs` to read like this:
537 // in src/japanese/mod.rs
539 pub use self::greetings::hello;
540 pub use self::farewells::goodbye;
547 The `pub use` declaration brings the function into scope at this part of our
548 module hierarchy. Because we've `pub use`d this inside of our `japanese`
549 module, we now have a `phrases::japanese::hello()` function and a
550 `phrases::japanese::goodbye()` function, even though the code for them lives in
551 `phrases::japanese::greetings::hello()` and
552 `phrases::japanese::farewells::goodbye()`. Our internal organization doesn't
553 define our external interface.
555 Also, note that we `pub use`d before we declared our `mod`s. Rust requires that
556 `use` declarations go first.
558 This will build and run:
562 Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
563 Running `target/phrases`
564 Hello in English: Hello!
565 Goodbye in English: Goodbye.
566 Hello in Japanese: こんにちは
567 Goodbye in Japanese: さようなら