Variables Exercises
Overview
These exercises teach the fundamentals of variable declaration, mutability, and initialization in Rust.
variables1 - The let Keyword
Concept: Declaring variables
fn main() {
let x = 5;
println!("x has the value {x}");
}Key Takeaway: Variables are declared with let. Without it, Rust doesn’t recognize the binding.
variables2 - Initialization & Type Inference
Concept: Variables must be initialized before use
fn main() {
let x = 42; // i32 inferred by default
// Or with explicit type annotation:
// let x: u8 = 42;
if x == 10 {
println!("x is ten!");
} else {
println!("x is not ten!");
}
}Key Takeaways:
- Rust requires initialization before use
- Type inference defaults integers to
i32 - You can annotate types explicitly:
let x: u8 = 42;
variables3 - Uninitialized Variables
Concept: Late initialization
fn main() {
let x: i32 = 42;
println!("Number {x}");
// Declare now, initialize later (but before use!)
let y: i32;
y = 42;
println!("Number {y}");
}Key Takeaway: You can declare and initialize separately, but you can’t read an uninitialized variable.
variables4 - Mutability
Concept: Variables are immutable by default
fn main() {
let mut x = 3; // `mut` makes it mutable
println!("Number {x}");
x = 5; // This is now allowed
println!("Number {x}");
}Key Takeaways:
- Immutability is a safety feature — prevents accidental changes
- Add
mutafterletto allow reassignment - This is a core Rust philosophy: explicit over implicit
variables5 - Shadowing
Concept: Creating a new variable with the same name
fn main() {
let number = "T-H-R-E-E";
println!("Spell a number: {number}");
let number = 3; // Shadowing — new variable, different type!
println!("Number plus two is: {}", number + 2);
}Key Takeaways:
- Shadowing lets you reuse names (unlike
mut, which keeps the same type) - The new binding can have a different type
- Useful for transforming values while keeping meaningful names
- Rust Book §3.1
variables6 - Constants
Concept: Compile-time constants with const
const NUMBER: u64 = 3;
fn main() {
println!("Number: {NUMBER}");
}Key Takeaways:
- Constants require a type annotation (always!)
- Naming convention:
SCREAMING_SNAKE_CASE - Constants are evaluated at compile time
- Cannot be
mut— they’re truly immutable forever