Rust Tuples
Fixed-size collections of mixed types
📦 What are Rust Tuples?
Tuples are fixed-size collections that can store multiple values of different types together. They're perfect for grouping related data temporarily, returning multiple values from functions, and pattern matching in Rust programs.
fn main() {
// Tuple with different types
let person = ("Alice", 30, true);
// Access elements by index
println!("Name: {}", person.0);
println!("Age: {}", person.1);
println!("Is student: {}", person.2);
}
Output:
Name: Alice
Age: 30
Is student: true
Tuple Characteristics
Fixed Size
Size determined at compile time
let tuple = (1, 2, 3);
Mixed Types
Can store different data types
let mixed = (42, "hello", true);
Index Access
Access elements using dot notation
let first = tuple.0;
Destructuring
Unpack values into variables
let (x, y, z) = tuple;
🔹 Creating Tuples
Different ways to create tuples in Rust:
fn main() {
// Basic tuple with mixed types
let coordinates = (10.5, 20.3);
// Tuple with explicit types
let person: (&str, i32, bool) = ("Bob", 25, false);
// Single element tuple (note the comma)
let single = (42,);
// Empty tuple (unit type)
let unit = ();
// Nested tuples
let nested = ((1, 2), (3, 4));
println!("Coordinates: {:?}", coordinates);
println!("Person: {:?}", person);
println!("Single: {:?}", single);
println!("Unit: {:?}", unit);
println!("Nested: {:?}", nested);
}
Output:
Coordinates: (10.5, 20.3)
Person: ("Bob", 25, false)
Single: (42,)
Unit: ()
Nested: ((1, 2), (3, 4))
🔹 Accessing Tuple Elements
Access tuple elements using dot notation with index:
fn main() {
let student = ("Emma", 22, "Computer Science", 3.8);
// Access individual elements
println!("Name: {}", student.0);
println!("Age: {}", student.1);
println!("Major: {}", student.2);
println!("GPA: {}", student.3);
// Store elements in variables
let name = student.0;
let age = student.1;
println!("Student {} is {} years old", name, age);
// Modify tuple elements (tuple must be mutable)
let mut scores = (85, 90, 78);
scores.0 = 95; // Change first score
scores.2 = 88; // Change third score
println!("Updated scores: {:?}", scores);
}
Output:
Name: Emma
Age: 22
Major: Computer Science
GPA: 3.8
Student Emma is 22 years old
Updated scores: (95, 90, 88)
🔹 Tuple Destructuring
Unpack tuple values into separate variables:
fn main() {
let point = (3.0, 4.0);
// Destructure into separate variables
let (x, y) = point;
println!("Point coordinates: x={}, y={}", x, y);
// Partial destructuring with underscore
let rgb = (255, 128, 0);
let (red, _, blue) = rgb; // Ignore green component
println!("Red: {}, Blue: {}", red, blue);
// Destructuring in function parameters
fn print_person(person: (&str, i32)) {
let (name, age) = person;
println!("{} is {} years old", name, age);
}
let alice = ("Alice", 28);
print_person(alice);
// Destructuring with different patterns
let data = (1, (2, 3), 4);
let (first, (second, third), fourth) = data;
println!("Values: {}, {}, {}, {}", first, second, third, fourth);
}
Output:
Point coordinates: x=3, y=4
Red: 255, Blue: 0
Alice is 28 years old
Values: 1, 2, 3, 4
🔹 Tuples in Functions
Use tuples to return multiple values from functions:
fn main() {
// Function returning a tuple
fn get_name_and_age() -> (&'static str, i32) {
("John", 35)
}
let person = get_name_and_age();
println!("Person: {:?}", person);
// Destructure the returned tuple
let (name, age) = get_name_and_age();
println!("Name: {}, Age: {}", name, age);
// Function that calculates multiple values
fn calculate_stats(numbers: &[i32]) -> (i32, i32, f64) {
let sum: i32 = numbers.iter().sum();
let max = *numbers.iter().max().unwrap_or(&0);
let average = sum as f64 / numbers.len() as f64;
(sum, max, average)
}
let data = [10, 20, 30, 40, 50];
let (total, maximum, avg) = calculate_stats(&data);
println!("Sum: {}, Max: {}, Average: {:.2}", total, maximum, avg);
// Function taking tuple as parameter
fn distance_from_origin((x, y): (f64, f64)) -> f64 {
(x * x + y * y).sqrt()
}
let point = (3.0, 4.0);
let dist = distance_from_origin(point);
println!("Distance from origin: {:.2}", dist);
}
Output:
Person: ("John", 35)
Name: John, Age: 35
Sum: 150, Max: 50, Average: 30.00
Distance from origin: 5.00
🔹 Tuple Methods and Operations
Working with tuples and common operations:
fn main() {
let coordinates = (10, 20, 30);
// Tuples implement Debug trait for printing
println!("Debug print: {:?}", coordinates);
// Tuples can be compared if all elements are comparable
let point1 = (1, 2);
let point2 = (1, 2);
let point3 = (2, 1);
println!("point1 == point2: {}", point1 == point2);
println!("point1 == point3: {}", point1 == point3);
// Tuples can be cloned if all elements are cloneable
let original = (String::from("hello"), 42);
let cloned = original.clone();
println!("Original: {:?}", original);
println!("Cloned: {:?}", cloned);
// Using tuples in match expressions
let status = (200, "OK");
match status {
(200, message) => println!("Success: {}", message),
(404, message) => println!("Not found: {}", message),
(code, message) => println!("Status {}: {}", code, message),
}
// Tuple as array indices (for 2D coordinates)
let grid = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
let position = (1, 2); // row 1, column 2
println!("Value at {:?}: {}", position, grid[position.0][position.1]);
}
Output:
Debug print: (10, 20, 30)
point1 == point2: true
point1 == point3: false
Original: ("hello", 42)
Cloned: ("hello", 42)
Success: OK
Value at (1, 2): 6