Lab: Types & traits
Scenario questions on enum pattern matching, trait objects, and iterator chains to consolidate the types-and-traits module.
- Predict match arm outcomes without running code
- Reason about trait objects and dynamic dispatch
- Trace iterator adapter chains to their output
This lab consolidates the types-and-traits module through scenario questions. Work through them before checking explanations — predicting outcomes and then reading the reasoning is more effective than reading first.
Part 1: Enum pattern matching
Knowledge check
- 1.What does this code print?
enum Coin { Penny, Dime, Quarter(String) } let c = Coin::Quarter(String::from("Alaska")); match c { Coin::Penny => println!("1"), Coin::Quarter(state) if state.starts_with("A") => println!("25 + {}", state), _ => println!("other"), } - 2.You define an enum with 6 variants and write a match with 5 arms plus a wildcard
_. You add a 7th variant. Does the code still compile? - 3.
if let Ok(v) = some_result { ... }is exactly equivalent to a match with one Ok arm and a wildcard Err arm.
Part 2: Trait objects and dynamic dispatch
Knowledge check
- 1.What is a trait object (
&dyn TraitorBox<dyn Trait>)? - 2.When should you prefer
Box<dyn Trait>over a genericT: Trait? - 3.A trait with a method that returns
Selfcan be used as a trait object (dyn Trait).
Part 3: Iterator chains
Knowledge check
- 1.What does this expression produce?
let result: Vec<i32> = (1..=5) .map(|x| x * 2) .filter(|x| x > &5) .collect(); - 2.You have
let v: Vec<Vec<i32>> = vec![vec![1,2], vec![3,4]];. Which expression produces[1, 2, 3, 4]as aVec<i32>? - 3.Calling
.map(|x| x * 2)on a vector immediately doubles all its elements.
Putting it together
The types-and-traits module builds a layered picture: enums model data shapes, traits describe capabilities, generics write code once for many types, and iterators apply those abstractions to sequences. Together these form the core of idiomatic Rust — most real Rust code uses all four constantly.
If any question surprised you, revisit the corresponding lesson. The best follow-up is to open a Rust playground or cargo new scratch and try the code yourself — the compiler's errors are precise teaching tools.
Where to go next
You've completed the intermediate track. The advanced track starts with concurrency — where ownership, Send/Sync, and closures combine to make data-race-free multi-threaded programming a compile-time guarantee.