6.7 KiB
Use
use
the keyword
This is used to bring paths into scope
pub
keyword is used to make items public
as
keyword for globs and external packages
Modules
Cheat Sheet
- Start from the Root Crate: compiler starts here to look for code to compile
- Normally src/main.rs for binary crates or src/lib.rs for library crates
- Declaring Modules: These are declared in the crate root file
- For example if you had a module called garden
- it would be declared by
mod garden;
- The complier would then look 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
- Inline, within curly brackets that replace the semicolon following
- Declaring submodules: in any other file you can declare submodules in any other file than the root
- it would be declared by
mod vegetables;
- The complier would then look in these places for the submodule
- 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
- Inline, directly following
- it would be declared by
- Paths to code in Modules: once a module is part of your crate, you can refer to the code in that module form anywhere else in that same crate as long as the privacy rules allow using that part of the code
- Example
Asparagus
is a struct/type in the graden vegetables module would be found atcrate::graden::vegetables::Asparagus
- Example
- Private vs. public: code is private by default to the parent module to make it public.
- To make a module public declare it with
pub mod
instead ofmod
. - To make items within the public module public as well add
pub
before their declaration
- To make a module public declare it with
- The
use
keyword: This is used to shorten the full path to just the last::
in the declaration- example use
crate::garden::vegetables::Asparagus
- to now
use crate::garden::vegetables::Asparagus;
- now can call this module by just
Asparagus
Here is how this example's file directory would look
backyard
├── Cargo.lock
├── Cargo.toml
└── src
├── garden
│ └── vegetables.rs
├── garden.rs
└── main.rs
src/main.rs
use crate::garden::vegetables::Asparagus;
pub mod garden;
fn main() {
let plant = Asparagus {};
println!("I'm growing {plant:?}!");
}
src/garden.rs
pub mod vegetables;
src/garden/vegetables.rs
#[derive(Debug)]
pub struct Asparagus {}
Grouping Related Code in Modules
used to group code together and make easier to reuse modules allow for the control of privacy, implementations needs to be declared as public otherwise it will be private by default not available to other modules if private
public modules and implementations can allow for different code to depend on it
this should be used to organize code like a file directory
Use with Modules
This is a quick way to bring into scope a module then refer to the public items associated with module
Use can be used with either the entire module or just one part of the module
use crate::example_mod::sub_mod;
use crate::example_mod::sub_mod::example_funct;
// --snip--
// consumption
sub_mod::example_funct();
example_funct();
The use statement must be in the module scope if defined in the same file
ex of proper use
mod another_mod {
use crate::example_mod::sub_mod::example_funct;
// --snip--
}
// dont do this but you can
use crate::example_mod::sub_mod::example_funct;
mod another_mod {
use super::example_funct;
super::example_funct();
// --snip--
}
ex not allowed
use crate::example_mod::sub_mod::example_funct;
mod another_mod {
// --snip--
}
Use the Idiomatic Path
use crate::example_mod::sub_mod;
this is the idiomatic path due to being able to call functions, structs, etc. inside the mod
use crate::example_mod::sub_mod::mod_fn;
this is not idiomatic due to specifying only one thing in the module
this is great for letting others know it is not defined in the same module/crate as where it is being called this is only for functions
for structs and enums it makes more sense to bring the whole object into scope then using the methods associated
this is just convention in rust
the exception to this convention is when bringing who items with the name name into scope because rust wont allow that and no one can read which call it is supposed to be
use std::fmt;
use std::io;
fn function1() -> fmt::Result {
// --snip--
}
fn function2() -> io::Result<()> {
// --snip--
}
Result makes no sense unless looking at input or slight differences
Then use the parent mod to do so if this is the case
Providing New Names with the as
Keyword
Here is the other solution to the similar names problem
use std::fmt::Result;
use std::io::Result as IoResult;
fn function1() -> Result {
// --snip--
}
fn function2() -> IoResult<()> {
// --snip--
}
as you can now see Result and IoResult may be called the same thing under the hood but now you can differentiate between the two
this is also an accepted convention in rust
Re-exporting Names with pub use
the name that is brough into scope with use is private, but you can make it public to the whole module then you can add pub before use
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
pub use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
hosting::add_to_waitlist();
}
this would be like defining it as if it was defining it in the scope that is desired
this also would have required front_of_house to also be marked public
this is useful when the internal structure of your code is different from how programmers would call your code
for example a customer would not think about frontend and backend they would think of add_to_waitlist and hosting not who's job it is
Will be added onto in ch 14
Nested Paths/Shortening Use
this is a technique to shorten the use vertical space that it can often take up
use std::cmp::Ordering;
use std::io;
// this is the same as
use std::{cmp::Ordering, io};
this specifies a common path between the two
this can reduce the number of times that use shows up by A LOT
Glob Operator on Use
Use if you want to bring all sub children of a path into scope
use std::collections::*;
This brings all public items defined in std::collections
into the current scope
This makes it harder to tell what names are used in scope and where a name in used in your program
This is often used when testing to bring everything under test into the tests module
This is also used as part of the prelude pattern