Variables & mutability in rust
By default, variables are immutable in Rust. Coming from a Python background, I have to keep in mind that this:
fn main() {
let var = 10;
println!("var = {}", var); // var = 10
var = 5; // try and reassign var
println!("var is now {}", var);
}
… will not compile.
The rust compiler gives a clear output of what went wrong:
error[E0384]: cannot assign twice to immutable variable `var`
|
2 | let var = 10;
| ---
| |
| first assignment to `var`
| help: make this binding mutable: `mut var`
3 | println!("var = {}", var); // var = 10
4 | var = 5; // try and reassign var
| ^^^^^^^ cannot assign twice to immutable variable
Once a value is assigned to var
, var
is bound
to that value until it goes out of scope.
Opting out of immutability
Variables can be made mutable using the mut
keyword:
fn main() {
let mut var = 10;
println!("var = {}", var); // var = 10
var = 5; // reassign var
println!("var is now {}", var); // var is now 5
}
This makes it clear when reading the code that var
expects
to be changed somewhere else.
Shadowing
Instead of making a variable mutable and reassigning it directly, rust provides another technique known as shadowing. Here's an example:
fn main() {
let var = 10; // not mutable
println!("var = {}", var); // var = 10
let var = 5; // shadow first var (10)
println!("var is now {}", var); // var is now 5
let var = var + 2; // shadow second var (5) and add 2 to it
println!("var + 2 = {}", var); // var + 2 = 7
}
var
remains immutable all through so trying to attach any
value to it without using let
to tell Rust you're
shadowing will not work.
Shadowing also allows changing the variable data type - something that making a variable mutable doesn't allow. An example of when to use this would be when writing a program that accepts a string and returns the number of characters in that string.
This works:
let hello = "hello";
let hello = hello.len(); // 5
This will not compile:
let mut hello = "hello";
hello = hello.len();
Output:
error[E0308]: mismatched types
|
3 | hello = hello.len();
| ^^^^^^^^^^^ expected `&str`, found `usize`
Variables vs constants
- Constants are declared with
const
keyword, variables withlet
- Constants cannot be made mutable
- Constants can only be assigned to constant expressions, not to values that are computed during runtime - like results of function calls