Modules
Section |
---|
Modules |
use keyword |
Declaring modules: In the crate root file (main.rs
or lib.rs
), you can declare new modules; say, you declare a “garden” module with mod garden;
(or pub mod garden;
for public); 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 (older style)
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 (older style)
In Rust, all items (functions, methods, structs, enums, modules, and constants) are private to parent modules by default. Items can access other items in the same module, even when private.
Items in a parent module can’t use the private items inside child modules, but items in child modules can use the items in their ancestor modules.
A clear explanation of Rust’s module system⮳
Use keyword
Create a shortcut to a path with the use
⮳ keyword once, and then use the shorter name everywhere else in the scope.
// For code from an external crate, the absolute path begins with the // crate name Here, the standard `std` library use std::collections::HashMap; // Glob - all public objects in `collections` are now in scope use std::collections::*; // With the following, `File` without prefix is available in the scope use std::fs::File; // The following is equivalent to `use std::io; use std::io::Write;` use std::io::{self, Write}; // Combine multiple `use` lines together with { } use std::{cmp::Ordering, fmt}; mod utils { pub fn insert_use() {} } // Absolute path - for code from the current crate, it starts with the // literal `crate`. use crate::modules::utils::insert_use; mod a { pub mod b {} } // A relative path starts from the current module and uses `self`, // `super`, or an identifier in the current module. use self::a::b; mod c { // 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 path. use super::a; } use std::fmt::Result; use std::io::Result as IoResult; // Alias mod front_of_house { pub mod hosting {} } // Reexporting - `pub use` re-exports the `hosting` module from the // root module, thus external code can use the path // `<crate>::hosting::add_to_waitlist()` instead of // `crate::front_of_house::hosting::add_to_waitlist()`. pub use front_of_house::hosting; fn main() {}
Idiomatic - bringing the function’s parent module into scope, not the function itself:
use front_of_house::hosting; mod front_of_house { pub mod hosting { pub fn add_to_waitlist() {} } } fn eat_at_restaurant() { hosting::add_to_waitlist(); } fn main() { eat_at_restaurant(); }
On the other hand, when bringing in structs, enums, and other items with use, it’s idiomatic to specify the full path.
use std::collections::HashMap; fn main() { let mut _map: HashMap<u32, String> = HashMap::new(); }