Rust
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Ownership and Borrowing
-
Section 4: Structuring Data
-
Section 5: Collections and Error Handling
-
Section 6: Traits and Generics
-
Section 7: Concurrency
-
Section 8: Building for the Web
-
Section 9: Memory and Performance
-
Section 10: More Standard Library and Ecosystem
-
Section 11: Advanced Rust
-
Section 12: Rust for Systems and WebAssembly
-
Section 13: Tooling and Best Practices
-
Section 14: Data Structures and Algorithms in Rust
-
Section 15: Practical Projects
-
Section 16: Interview Practice
-
Section 17: std::collections In Depth
-
Section 18: std::io and std::fs In Depth
-
Section 19: std::net
-
Section 20: std::option and std::result In Depth
-
Section 21: std::iter In Depth
-
Section 22: std::sync In Depth
-
Section 23: std::string and std::str
-
Section 24: Cargo and Crates.io Ecosystem
-
Section 25: Popular Crates Ecosystem
-
Section 26: Rust Memory Model Deep Dive
-
Section 27: More Practice Exercises
-
Section 28: More Interview Practice
-
Section 29: Async Rust Deep Dive
-
Section 30: Tokio Ecosystem In Depth
-
Section 31: Error Handling Ecosystem Deep Dive
-
Section 32: Serde In Depth
-
Section 33: Web Development with Rust Deep Dive
-
Section 34: Database Access Ecosystem
-
Section 35: Rust for Embedded Systems Deep Dive
-
Section 36: Rust Macros In Depth
-
Section 37: Advanced Trait System
-
Section 38: Unsafe Rust In Depth
-
Section 39: Rust CLI Development
-
Section 40: Testing Ecosystem Deep Dive
-
Section 41: WebAssembly Deep Dive
-
Section 42: Rust Design Patterns
-
Section 43: More Data Structures in Rust
-
Section 44: Final Practice Projects
-
Section 45: Rust Performance Optimization
-
Section 46: Rust Ecosystem Tooling
-
Section 47: More Interview and Review
7: Data Types
I want to build a simple character sheet for a rogue-like game. I've got the basic syntax down from the last few lessons, but now I need to actually store some data. I'm just going to start typing and see where the compiler pushes back—that's usually where the real learning happens in Rust.
The "Just a Number" Trap
First, I'll start with the obvious stuff: health and gold. I'll just let Rust infer the types for a second.
let health = 100;
let gold = 50;
health = 95.5; // I'll just take a little bit of damage
Right away, the compiler hits me with a mismatched types error. It's telling me that health is an integer, but I'm trying to assign a float to it. In some languages, this happens silently (and causes bugs later), but Rust is refusing to budge. It decided health was an i32 (a 32-bit signed integer) because that's the default for whole numbers.
If I want decimals, I have to be explicit. I'll change it to a float. I usually go with f64 because the performance hit is negligible on modern machines, and the precision is better.
let health: f64 = 100.0;
let gold: u32 = 50; // Gold can't be negative, so unsigned is better here
Notice that u32? That's an unsigned integer. Since you can't have negative gold in my game, using a u type is a way of encoding that rule directly into the data type. It's a small detail, but it saves you from writing if gold < 0 checks everywhere.
Truths, Lies, and Single Letters
Now I need to track if the player is poisoned and what their character grade is. This is where the simpler scalars come in.
let is_poisoned = true;
let rank = 'A';
The bool type is straightforward. But look at rank. I used single quotes 'A', not double quotes. In Rust, double quotes are for strings, but single quotes are for char. A char in Rust is actually 4 bytes because it represents a Unicode scalar value. This means I could actually use an emoji for a rank if I wanted to—Rust doesn't just limit you to ASCII.
Bundling the Chaos
My code is getting cluttered with individual variables. I want to group the player's coordinates (X, Y) together. I don't want to create a whole new custom structure yet; I just want a quick bundle.
let position = (0, 0);
println!("Player is at x: {}, y: {}", position.0, position.1);
This is a Tuple. It's incredibly handy when you want to return two or three things from a function without naming them. The weird part is the .0 and .1 syntax to access the data. It feels a bit clunky, but it's the fastest way to group different types together. I could even do (10, "Forest", true)—a tuple doesn't care if the types are different.
The Rigid List
Finally, I want to store the player's base attributes: Strength, Dexterity, and Intelligence. These will always be three numbers, and they'll always be integers. A tuple is too loose for this; I want a fixed-size list.
let stats = [10, 15, 8];
This is an Array. Unlike the tuple, every single element in an array must be the same type. If I tried to put a string in there, the compiler would lose its mind. Also, the size is fixed. Once I say it's 3 elements long, it's 3 elements long for the rest of the program's life.
If I try to access stats[3], the program will panic at runtime because the index is out of bounds. Rust doesn't let you accidentally wander off the end of your array into random memory—it would rather crash the program than let you read garbage data.
📋 Practical Task
Exercise: Building a Character Stat Sheet
Create a Rust program that models a character's state using the different data types we explored. Your program should include the following:
- A floating-point variable for
experience_points. - An unsigned integer for
level. - A boolean for
is_alive. - A character for
alignment(e.g., 'L' for Lawful, 'C' for Chaotic). - A tuple named
coordinatescontaining two integers (x, y). - An array named
inventory_weightscontaining fourf32values representing the weight of items in the player's bag.
Print all these values to the console using println!. Make sure you access the tuple elements using the dot notation (.0, .1) and the array elements using square brackets ([0]).
There are no comments for now.