In Session 6 of the Polkadot Kisumu Bootcamp, we dived deep into one of the most practical and powerful data structures in Rust: Vectors.
If youβve ever needed to store a list of items that can change size, vectors are your best friend in Rust.
What Is a Vector?
A vector is a resizable array that stores values on the heap. It's useful when you donβt know the size of your data at compile time.
fn main() {
let mut numbers = Vec::new();
numbers.push(10);
numbers.push(20);
println!("{:?}", numbers); // Output: [10, 20]
}
π Using .push() and .pop()
These are the basic ways to grow or shrink a vector.
fn main() {
let mut fruits = vec!["apple", "banana"];
fruits.push("mango"); // Add item
fruits.pop(); // Remove last item
println!("{:?}", fruits); // Output: ["apple", "banana"]
}
βοΈ Slices β Borrowing Part of a Vector
Slices let you access a section of the vector without taking ownership.
fn main() {
let data = vec![1, 2, 3, 4, 5];
let slice = &data[1..4];
println!("{:?}", slice); // Output: [2, 3, 4]
}
This is memory-efficient and avoids unnecessary copying.
𧬠Generics β Writing Flexible Code
Generics in Rust let you write functions or types that work with any data type, as long as the type meets certain conditions.
Instead of writing duplicate code for each type (i32, String, etc.), you can use a generic type parameter like T.
fn print_all<T: std::fmt::Debug>(items: Vec<T>) {
for item in items {
println!("{:?}", item);
}
}
What's Happening:
T is a placeholder for any type.
T: std::fmt::Debug means the type T must implement the Debug trait so it can be printed.
You can now call print_all() with Vec, Vec<&str>, Vec, etc.
fn main() {
let numbers = vec![1, 2, 3];
let names = vec!["Ann", "Ben", "Chris"];
print_all(numbers);
print_all(names);
}
π§ Generics = less repetition + more flexibility.
This is the Rust way to write clean, DRY (Don't Repeat Yourself), scalable code.
π Iteration Methods β Understanding Ownership in Loops
.iter() β Immutable Borrow
You borrow each item without modifying or taking ownership.
let nums = vec![1, 2, 3];
for n in nums.iter() {
println!("{}", n); // Can read, but not modify
}
// nums is still usable here
Use this when you just want to read from the vector.
.iter_mut() β Mutable Borrow
You borrow each item mutably, which means you can change the values.
let mut nums = vec![1, 2, 3];
for n in nums.iter_mut() {
*n *= 2; // Modify in-place
}
println!("{:?}", nums); // Output: [2, 4, 6]
Use this when you need to edit values in the vector.
.into_iter() β Take Ownership
You move each item out of the vector β meaning the original vector is no longer usable after the loop.
let nums = vec![1, 2, 3];
for n in nums.into_iter() {
println!("{}", n);
}
// nums is now invalid β ownership moved
β Use this when you're done with the vector and want to consume it completely.
Why This Matters
Understanding generics and iteration methods gives you real power in Rust:
- You write once, reuse everywhere (generics).
- You control how memory is accessed, modified, or moved (iterators).
- It ties directly back to ownership and borrowing, which are core to writing safe, high-performance Rust.
This builds on earlier sessions like ownership and borrowing making your code more safe, clean, and production-ready.
Top comments (0)