Variables and Mutability in Rust

let vs let mut

By default, variables in Rust are immutable, meaning you cannot change their value after binding; you must explicitly declare a variable as mutable using the `let mut` keyword to allow reassignment.

By default, variables in Rust are immutable, meaning you cannot change their value after binding; you must explicitly declare a variable as mutable using the let mut keyword to allow reassignment. This design prevents accidental data changes and makes ownership rules clearer, but it requires you to be intentional about which data needs to change.

Here is a practical example showing the difference between the two:

fn main() {
    // Immutable by default
    let x = 5;
    // x = 6; // This would cause a compile-time error: "cannot assign twice to immutable variable `x`"

    // Explicitly mutable
    let mut y = 5;
    y = 6; // This works fine
    println!("y is now: {}", y);

    // Shadowing allows you to create a new variable with the same name
    // without needing `mut`, effectively "changing" the binding
    let z = 5;
    let z = z + 1; // Creates a new immutable `z` that shadows the previous one
    println!("z is now: {}", z);
}

If you try to reassign an immutable variable, the compiler will immediately stop you with an error. This is a safety feature, not a limitation. However, if you only need to change a value once or in a specific scope, you can use shadowing (as seen with z above) instead of let mut. Shadowing creates a new variable that hides the old one, which is often preferred when the new value has a different type or when you want to ensure the variable cannot be changed again after that specific point.

Use let mut when you need to modify the same variable multiple times within a scope, such as in a loop or when accumulating a sum. For example:

fn main() {
    let mut count = 0;
    
    for i in 0..5 {
        count += 1; // Reassigning `count` requires `mut`
    }
    
    println!("Count: {}", count);
}

In summary, default to let for immutability to catch bugs early. Only add mut when you have a specific, logical reason for the variable to change state. If you find yourself needing mut everywhere, it might indicate your function is doing too much or that you should be returning new values instead of modifying existing ones.