Rust - Variables
Rust - Variables and Mutability
Section titled “Rust - Variables and Mutability”A variable is a named storage location that programs can manipulate. In Rust, variables are not just about storing data; they are deeply integrated with the language’s core principles of safety and ownership.
Declaring Variables
Section titled “Declaring Variables”You declare a variable using the let keyword. Rust is a statically typed language, which means it must know the type of all variables at compile time. However, the compiler is smart and can usually infer the type based on the value you assign.
fn main() { // The compiler infers the type of `x` as i32 (integer) let x = 5;
// Here, we explicitly annotate the type as a 64-bit float let y: f64 = 3.14;
println!("The value of x is: {}", x); println!("The value of y is: {}", y);}Naming Rules
Section titled “Naming Rules”Variable names in Rust follow the snake_case convention, where all letters are lowercase and words are separated by underscores. They can contain letters, numbers, and underscores, but must start with a letter or an underscore.
Immutability by Default
Section titled “Immutability by Default”One of Rust’s key safety features is that variables are immutable by default. Once a value is bound to a name, you cannot change that value.
fn main() { let x = 5; println!("The value of x is: {}", x);
// The following line will cause a compile-time error! // x = 6; // error[E0384]: cannot assign twice to immutable variable `x`
// println!("The value of x is now: {}", x);}This compile-time check prevents a whole class of bugs where a value is accidentally changed. When you know a value won’t change, it’s easier to reason about your code.
Mutability
Section titled “Mutability”Of course, sometimes you need to change a variable’s value. To make a variable mutable, you must explicitly opt-in by using the mut keyword.
fn main() { let mut x = 5; println!("The value of x is: {}", x);
x = 6; println!("The value of x is now: {}", x);}Output
Section titled “Output”The value of x is: 5The value of x is now: 6Using mut signals to other developers (and to yourself) that this variable’s value is expected to change during its lifetime.
Shadowing
Section titled “Shadowing”Rust allows you to declare a new variable with the same name as a previous variable. This is called shadowing. The new variable “shadows” the old one, and the old variable is inaccessible from that point on in the scope.
fn main() { let x = 5;
// a new `x` is created, shadowing the first one. let x = x + 1;
{ // in this inner scope, a third `x` is created, shadowing the second one. let x = x * 2; println!("The value of x in the inner scope is: {}", x); }
// when the inner scope ends, the third `x` is gone, and we're back to the second one. println!("The value of x is: {}", x);}Output
Section titled “Output”The value of x in the inner scope is: 12The value of x is: 6Shadowing is different from marking a variable as mut. A key benefit of shadowing is that it allows you to change a variable’s type while reusing its name, which is often useful for conversions.
fn main() { let spaces = " "; // `spaces` is a string slice let spaces = spaces.len(); // `spaces` is now shadowed by a new variable of type `usize`
println!("There are {} spaces.", spaces);}This is allowed because we are creating a completely new variable with let. If we tried to do this with mut, it would fail because you cannot change a variable’s type.