Mutability

Coming from C and C++, the following is quite normal:

#include <stdio.h>
int main() {
   int i = 5;
   i += 1;
   printf("%d\n", i);
   return 0;
}

However, this doesn't work in Rust (there is no ++ operator):

fn main() {
    let i = 5;
    i += 1;
    println!("{i}");
}

You get the compiler error cannot assign twice to immutable variable i. That's because let creates an immutable variable. It's the same as typing const int i = 5; in C or C++.

Making a Mutable Variable

To mark a variable as mutable, you have to explicitly declare it as such:

fn main() {
    let mut i = 5;
    i += 1;
    println!("{i}");
}

So why wouldn't you define everything as mutable?

  • Your program gains some clarity from the knowledge that a variable won't change.
  • Functional-style programming tends to prefer not reusing variables.
  • If you accidentally mutate a variable later, the compiler will stop you.

You can make everything let mut, and then use the linter (cargo clippy or your IDE) to highlight the variables that don't need it---but that's a crutch and should be avoided as you gain experience.

Shadowing

You can also make use of shadowing. This is popular in many functional styles. It can also be confusing. I recommend adopting a style that suits you.

Take the following immutable code:

fn main() {
    let i = 5;
    let i_plus_one = i + 1;
    println!("{i}");
}

Your variables are immutable, and you are making it clear what's going on in your algorithm by naming each subsequent step. That's great until you get to a big algorithm and start running into i_log10_times_3... so you'll often find that "shadowing" is used to remove previous editions of a variable name from circulation as the calculation progresses:

fn main() {
    let i = 5;
    let i = i + 1;
    println!("{i}");
}

Shadowing is useful with scope (which we'll talk about in a moment). Within a scope, you can shadow a parent-scope's variable names---and get them back at the end of the scope. For example:

fn main() {
    let i = 5;
    {
        let i = i + 1;
        println!("{i}");
    }
    println!("{i}");
}