Reading — step 1 of 5
Learn
Vec: Growable Arrays
Vec<T> is Rust's growable array — the default collection, the one you reach for first, and (not coincidentally) your first daily-driver generic type: Vec<i32> holds i32s, Vec<String> holds Strings, and the <T> machinery guarantees at compile time that you never fish a String out of a Vec of numbers.
Creating and growing
let mut nums: Vec<i64> = Vec::new(); // empty — needs mut to grow
nums.push(10);
nums.push(20);
let nums = vec![10, 20, 30]; // the vec! macro: literal + contents
let zeros = vec![0; 5]; // [0, 0, 0, 0, 0] — value; count
push appends, pop removes and returns the last element, len() counts, .is_empty() asks. A Vec owns its elements (heap-allocated, freed when the Vec drops) — it's the String of collections, and &[T] (a slice) is its &str: functions that only need to read should take &[i64], and a &Vec<i64> coerces to it automatically.
Reading: two doors, different failure modes
let v = vec![1, 2, 3];
v[1] // 2 — direct indexing. Out of bounds? PANIC, immediately.
v.get(1) // Some(&2) — and v.get(99) is None: no panic, you decide.
This pair is a Rust design signature you'll see everywhere: the convenient door that crashes loudly on misuse, and the careful door that returns an Option and makes you handle absence. Grader input with promised bounds → index freely. Anything user-shaped → get. (Contrast with C, where out-of-bounds reads don't crash — they hand you garbage and a security advisory. Rust's panic is the good outcome.)
Iterating
for n in &v { // borrow the elements — the everyday form
println!("{n}");
}
for n in &mut v_mut { // borrow mutably to modify in place
*n *= 2; // * follows the reference — chapter 4 formalizes this
}
That & is doing real work: for n in v (no &) consumes the Vec — it's gone afterward. Until the ownership chapter explains why, the habit is: iterate with &, and the compiler will tell you on the rare day you want otherwise.
Your exercise: Largest Number
Read numbers, print the largest — the tracker pattern, sibling of the accumulator:
let mut best = i64::MIN; // start at the floor
for n in numbers {
if n > best {
best = n;
}
}
println!("{best}");
Two classic bugs to dodge: initialize with i64::MIN (or the first element) — starting at 0 breaks on all-negative input, the test case that exists precisely to catch it; and compare with > per the spec (with >= ties keep the last max — indistinguishable for values, wrong the moment an exercise asks for the index).
Worth knowing after you've written the loop by hand: Rust's iterators can do this in one line — numbers.iter().max() (it returns an Option, empty input being a real case). Write the manual version for this exercise; the Iterators lesson makes the one-liners honest.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…