Step 1 of 7
Modules and privacy
As a program grows, you need a way to group related code and to hide the details. A module is a named container for functions, structs, enums, constants and other modules. You create one with mod:
mod arena {
pub fn welcome(name: &str) {
println!("Welcome to the arena, {name}!");
open_gates();
}
fn open_gates() {
println!("(the gates creak open)");
}
}
fn main() {
arena::welcome("Ferris");
}
Welcome to the arena, Ferris!
(the gates creak open)
Piece by piece:
mod arena { ... }defines a module namedarena. Everything inside lives in thearenanamespace, so its names can't clash with names elsewhere.arena::welcomeis a path: the module,::, then the item. It's the same::you've used inString::fromandstd::io::stdin.- Items in a module are private by default: usable inside the module, invisible outside it.
pubmakes an item public. welcomeis public, somaincan call it.open_gatesis private, butwelcomecan call it because they're in the same module.
Why private by default? A module's public items are its interface: what others may rely on. Private items are details you can change or delete later without breaking anyone. At work this matters a lot: if a helper isn't pub, you know nobody outside depends on it.
Calling a private function
mod arena {
pub fn welcome() {
println!("Welcome!");
}
fn secret_door() {
println!("You found the secret door");
}
}
fn main() {
arena::welcome();
arena::secret_door();
}
error[E0603]: function `secret_door` is private
The full message points at the definition (note: the function `secret_door` is defined here), so you can decide whether it should be pub or whether you're reaching for something you shouldn't.
Modules inside modules
Modules nest, and every module on a path must be reachable:
mod garden {
pub mod vegetables {
pub fn harvest() -> u32 {
12
}
}
pub fn report() {
println!("harvested {} carrots", vegetables::harvest());
}
}
fn main() {
garden::report();
println!("{}", garden::vegetables::harvest());
}
harvested 12 carrots
12
The privacy rule in one sentence: a private item is visible in its own module and in all the modules inside it; pub also makes it visible wherever its parent module is visible. So a child can use its parent's private items, but a parent can't use its child's private items.
Common mistakes
pubon the function but not on the module. Ifvegetablesweren'tpub,mainwould geterror[E0603]: module `vegetables` is private, even thoughharvestispub. Every step of the path has to be visible.- Expecting a module to see its parent's names automatically. Modules aren't nested blocks; the next step shows how to reach outward with paths.
Your task
Fill in the blanks: declare the module scoreboard, and make record public so main can call it. The program prints Ferris: 120 pts.
Challenge 2
Move the two conversion functions into a module named temperature, and make them public, so that temperature::c_to_f and temperature::f_to_c work. The hidden tests call them through the module path.
Challenge 3
Build this module structure from scratch:
- a module
shopcontaining a public modulepricing; - in
pricing: a public functionwith_tax(cents: u32) -> u32that adds 20% (cents * 120 / 100) and then rounds down to a multiple of 10 using a private helperround_to_ten(cents: u32) -> u32(cents / 10 * 10); - in
shop: a public functionreceipt(cents: u32) -> Stringthat returns"total: 1200 cents"for1000, usingpricing::with_tax.
The tests call shop::pricing::with_tax and shop::receipt.