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 mut after let to 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

Rust Book Reference