Rust: Variables, Mutability, Immutability and Functions
Rust
Systems programming language focused on safety and speed.
Developed by Mozilla Research.
Key features:
Zero-cost abstractions
Memory safety without garbage collection
Ownership system for manual memory management
Statically typed
Variables
Used to store data in memory.
Immutable by default.
Immutability: Value cannot be changed after assignment.
To make a variable mutable, use the
mutkeyword.
Immutability
Example:
let x = 5; // x is immutable x = 6; // Error!Immutability prevents accidental changes.
Mutability
Example:
let mut y = 5; y = 6; // y is now mutableCompiler infers data type upon initialization; manual annotation may be needed.
Constants
Defined using the
constkeyword.Must be set to a constant expression.
Valid for the entire program duration.
Data type must be annotated.
Example:
const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
Variable Shadowing
Allows re-declaring a variable with the same name.
Creates a new variable instead of mutating the existing one.
Can change data types during shadowing.
Example:
let spaces = " "; let spaces = spaces.len(); // spaces is now a number
Scalar Types
Integers, floating-point numbers, booleans, characters.
Signed integers: -(2^{n-1}) to 2^{n-1} - 1
Unsigned integers: 0 to 2^n - 1
Integer Types
i8,i16,i32,i64,i128,isize(signed)u8,u16,u32,u64,u128,usize(unsigned)
Integer Literals
Decimal:
100_000Hex:
0xffOctal:
0o77Binary:
0b1111_0000Byte (u8 only):
b'A'
Compound Data Types
Tuples
Fixed-size collection of different types.
Created using parentheses
().Access elements using 0-based indexing.
let person: (i32, f64, char) = (25, 6.2, 'A'); let age = person.0;Unit tuple
()has special uses.
Arrays
Fixed-size collection of the same type.
Stored in contiguous memory.
Access elements using 0-based indexing.
let numbers: [i32; 5] = [1, 2, 3, 4, 5]; let first = numbers[0];
Basic Input and Output
Example:
use std::io; fn main() { println!("What is your name?");let mut name = String::new(); io::stdin() .read_line(&mut name) .expect("Failed to read line"); println!("Hello, {}!", name); }
Expressions and Return Values
The return value of a function is the value of the final expression.
Returning without the
returnkeywordfn five() -> i32 { 5 }
Functions
Type-safe and expressive
Example:
fn plus_one(x: i32) -> i32 { x + 1 }
Parameters
fn print_name(name: &str) {
println!("Hello, {}!", name);
}
Control Flow
If statement
if value.len() == 1 {
println!("everything okay!");
} else {
println!("too long!");
}
While loop
let mut remaining_iterations = 10;
while remaining_iterations != 0 {
println!("{remaining_iterations}!");
remaining_iterations -= 1;
}
Looping through collections
Needs to implement the Iterator trait.
fn print_array(arr: &[i32]) {
for element in arr {
println!("The value is: {}", element);
}
}
Looping through a range
.rev()reverses a range.
fn count_down(starting_value: i32) {
for i in (0..starting_value).rev() {
println!("{}", i);
}
}
Infinite loops
loop {}loops won’t terminate, break needs to be called explicitly.
fn loop_value() {
let mut times_looped = 0;
let times_looped_time_two = loop {
times_looped += 1;
if times_looped == 10 {
break times_looped * 2;
}
};
println!("The result is {times_looped_time_two}");
}