Declaring Variables in Rust
Immutable Variables
By default, variables in Rust are immutable. This means their values cannot change after being assigned.
fn main() {
let x = 5; // Immutable variable
println!("The value of x is: {}", x);
// x = 6; // Error: Cannot assign to immutable variable
}
Mutable Variables
To change the value of a variable, declare it as mutable using the mut keyword.
fn main() {
let mut y = 10; // Mutable variable
println!("Initial value of y: {}", y);
y = 20; // Allowed because y is mutable
println!("Updated value of y: {}", y);
}
Shadowing
Rust allows you to declare a new variable with the same name as a previous one. This process is called shadowing. It is different from mutability because the original variable remains immutable.
fn main() {
let z = 3;
println!("Value of z: {}", z);
let z = z + 1; // Shadowing
println!("New value of z: {}", z);
}
Constants
Constants are immutable and cannot be changed after being declared. They are defined using the const keyword and must have an explicitly defined type.
const MAX_POINTS: u32 = 100_000; // Underscores for readability
fn main() {
println!("The maximum points are: {}", MAX_POINTS);
}
Key Features of Constants:
- Constants are always immutable.
- Constants must have a type annotation.
- Constants can be defined outside of functions, making them accessible throughout the program.
Variable Scope and Lifetime
Variables in Rust have a scope, which is the region of the program where the variable is valid. A variable is no longer valid after it goes out of scope.
fn main() {
{
let a = 42; // a is valid within this block
println!("Value of a: {}", a);
} // a goes out of scope here
// println!("Trying to access a: {}", a); // Error: a is not valid here
}
Type Inference and Explicit Typing
Rust can infer the type of a variable based on the value assigned to it. However, you can also explicitly specify the type.
- Type Inference:
let b = 4.5; // Rust infers that b is of type f64
println!("Value of b: {}", b);
- Explicit Typing:
let c: i32 = 100; // Explicitly declaring c as a 32-bit integer
println!("Value of c: {}", c);
Multiple Variable Binding
Rust allows multiple variables to be declared in a single statement.
fn main() {
let (x, y, z) = (10, 20, 30); // Declaring multiple variables
println!("x: {}, y: {}, z: {}", x, y, z);
}
Examples
Example 1: Immutable vs Mutable Variables
fn main() {
let name = "Rust"; // Immutable
println!("Programming language: {}", name);
let mut age = 10; // Mutable
println!("Version age: {}", age);
age = 12;
println!("Updated version age: {}", age);
}
Example 2: Using Constants
const PI: f64 = 3.14159;
fn main() {
let radius = 5.0;
let area = PI * radius * radius;
println!("The area of the circle is: {}", area);
}
Example 3: Shadowing
fn main() {
let price = 50;
let price = price + 10; // Shadowing the previous price
let price = price * 2;
println!("Final price: {}", price);
}
Common Errors with Variables
- Assigning to Immutable Variables:
- Error: cannot assign twice to immutable variable.
- Solution: Use
mut
for mutable variables.
- Uninitialized Variables:
- Error: use of possibly uninitialized variable.
- Solution: Always initialize variables before use.
- Out-of-Scope Access:
- Error: borrow of moved value.
- Solution: Ensure variables are accessed within their scope.
Exercises
- Create a program that uses a mutable variable to store a counter and increments it in a loop.
- Write a program to demonstrate variable shadowing.
- Define a constant for the speed of light and use it in a calculation.