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.