Rust — Variables
Variables are immutable by default
The single most surprising line for newcomers:
let x = 5;
x = 6; // ❌ COMPILE ERROR: cannot assign twice to immutable variable
Rust makes immutability the default so the compiler (and readers) can assume values don't change unless declared otherwise. Opt into change explicitly:
let mut x = 5; // mut = mutable
x = 6; // ✓ fine now
Read let mut x as "I intend to change this." If you declare mut and never change it, the compiler warns you — defaults keep code honest.
Type inference — annotations usually optional
let count = 10; // inferred as i32
let price = 9.99; // inferred as f64
let name = "Ada"; // &str
let ratio: f32 = 0.25; // annotation needed when default differs
Annotate when the compiler can't guess (parsing, empty collections) or for public function signatures:
fn parse_count(text: &str) -> i32 {
text.trim().parse().expect("not a number")
}
Shadowing — new binding, same name
let spaces = " "; // string
let spaces = spaces.len(); // number — completely legal
Shadowing creates a new variable; the old one is gone but unchanged. This enables idiomatic transformation chains:
let input = " 42 ";
let input = input.trim();
let input: i32 = input.parse().expect("number");
// 'input' always holds the most meaningful form of itself
Contrast with mut, which cannot change type:
let mut spaces = " ";
spaces = spaces.len(); // ❌ expected &str, found usize
Constants — compile-time and UPPERCASE
const MAX_POINTS: u32 = 100_000;
fn main() {
println!("limit: {}", MAX_POINTS);
}
let | const | |
|---|---|---|
| Value fixed at | runtime | compile time |
| Type annotation | optional | required |
| Can shadow | yes | no |
| Usable outside functions | no | yes (global scope) |
Naming convention: UPPER_SNAKE_CASE with underscores as thousand separators.
Scope — curly braces rule
{
let inner = 42;
println!("{}", inner); // ✓ alive here
}
// println!("{}", inner) // ❌ out of scope
Variables die at their closing brace; memory is freed automatically at that moment (this is ownership working).
Unused variables warn
let unused = 3; // ⚠ warning: unused variable
let _ignored = 4; // underscore prefix silences it deliberately
let _ = some_result; // bare underscore: explicitly discard
Mini Practice
- Trigger the immutable-assignment error; fix with
mut. - Shadow a string through trim → parse → int in three lets.
- Try to change a
mutstring's type; read the error. - Declare a const with underscore separators; print it.
- Create an unused variable, then silence it both ways.
Next: data types →
Related Topics
Frequently Asked Questions about Variables
What is Variables in Rust?
Variables is a fundamental concept in Rust. This lesson explains it step by step with clear examples, making it easy for beginners to understand.
How do I learn Variables?
Start by reading the explanation above, then try the code examples. Practice by modifying the examples and experimenting with different values. Hands-on practice is the best way to learn Variables.
Why is Variables important in Rust?
Variables is essential for Rust development. Understanding this concept will help you write better code and solve real-world problems more effectively.