Exerpad
🔥1
10 XP
Lv.1 Beginner
Log In

Grouping Data

Sometimes you need to keep related pieces of information together — like the x and y position of a character in a game, or a pet's name and species. Rust gives you two great ways to do this: tuples and structs!

Tuples

A tuple groups several values into one bundle. The values can be different types:

rust
fn main() {
let point = (3, 7);
let player = ("Luna", 100, true);
println!("Point: {:?}", point);
println!("Player: {:?}", player);
}

Each value in a tuple has a type, so point has the type (i32, i32) and player has the type (&str, i32, bool).

Accessing Tuple Elements

You can grab individual values from a tuple using .0, .1, .2, and so on:

rust
fn main() {
let player = ("Luna", 100, true);
println!("Name: {}", player.0);
println!("Score: {}", player.1);
println!("Active: {}", player.2);
}

Remember — just like vectors, tuple indexes start at 0!

Destructuring Tuples

Instead of using .0 and .1, you can destructure a tuple to give each value its own name:

rust
fn main() {
let point = (5, 12);
let (x, y) = point;
println!("x is {} and y is {}", x, y);
}

This is like unpacking a box — you pull out each item and label it. Much easier to read than point.0 and point.1!

Structs

Tuples are great for quick groupings, but what if you have lots of fields? It's hard to remember what .0 and .3 mean! That's where structs come in. A struct lets you give a name to each field:

rust
#[derive(Debug)]
struct Pet {
name: String,
species: String,
age: i32,
}

fn main() {
let my_pet = Pet {
name: String::from("Whiskers"),
species: String::from("cat"),
age: 3,
};
println!("{:?}", my_pet);
println!("{} is a {} who is {} years old", my_pet.name, my_pet.species, my_pet.age);
}

A few things to notice:

  • We define the struct outside of main with struct Pet { ... }
  • #[derive(Debug)] lets us print the whole struct with {:?}
  • We use String::from("...") for text fields (not just "...")
  • We access fields by name: my_pet.name, my_pet.species

Methods with impl

You can add methods to a struct using an impl block. Methods are functions that belong to your struct:

rust
#[derive(Debug)]
struct Rectangle {
width: f64,
height: f64,
}

impl Rectangle {
fn area(&self) -> f64 {
self.width * self.height
}

fn describe(&self) {
println!("Rectangle: {} x {} (area: {})", self.width, self.height, self.area());
}
}

fn main() {
let rect = Rectangle { width: 5.0, height: 3.0 };
println!("Area: {}", rect.area());
rect.describe();
}
  • &self means "this struct instance" — it lets the method read the struct's fields
  • You call methods with a dot: rect.area(), rect.describe()

Summary

ConceptWhat it does
(1, "hi", true)Creates a tuple with mixed types
tuple.0, tuple.1Accesses tuple elements by position
let (a, b) = tuple;Destructures a tuple into variables
struct Name { field: Type }Defines a struct with named fields
Name { field: value }Creates a struct instance
instance.fieldAccesses a struct field
#[derive(Debug)]Lets you print a struct with {:?}
impl Name { fn method(&self) {} }Adds methods to a struct

Now let's practice grouping data with tuples and structs!