12 · Vec and Collections
Vec<T> is the standard growable array. Creating or pushing into a Vec requires the !alloc effect — the compiler makes heap allocation explicit in the type. Iteration is zero-cost: for loops and iterator adapters like map, filter, and fold compile to the same code as a hand-written loop.
fn main() !io !alloc { // Build a Vec by pushing. let mut nums: Vec<i32> = Vec::new(); for i in 0..5 { nums.push(i * i); // 0, 1, 4, 9, 16 }
// Iterate by reference. println!("squares:"); for n in &nums { println!(" {}", n); }
// Functional-style — produces a new Vec. let evens: Vec<i32> = nums.iter() .filter(|&&x| x % 2 == 0) .copied() .collect() !alloc;
println!("even squares: {:?}", evens);
// Fold to sum. let total: i32 = nums.iter().fold(0, |acc, &x| acc + x); println!("sum = {}", total);
// Vec::from for a known-size literal. let words: Vec<str> = Vec::from(["alpha", "beta", "gamma"]) !alloc; println!("words: {:?}", words);}Output
Section titled “Output”squares: 0 1 4 9 16even squares: [0, 4, 16]sum = 30words: ["alpha", "beta", "gamma"]What the compiler sees
Section titled “What the compiler sees”Every !alloc site in the function body is visible in the function signature. This makes memory allocation auditable by reading type signatures alone — no hidden allocations from library calls. The iterator chain (filter → copied → collect) is fused by the compiler into a single pass with no intermediate allocations. Out-of-bounds indexing via nums[i] carries !panic; use nums.get(i) for a bounds-checked Option<&i32> with no effect.
Next → 13 · Error Handling