Rust Fundamentals · 25 XP Pro

Iterators

An iterator produces a sequence of items one at a time. v.iter() walks a vector by reference; for x in &v uses it behind the scenes. The real power is that iterators chain into small pipelines of adapters that end in a consumer.

let v = vec![1, 2, 3, 4, 5, 6];

let total: i32 = v.iter().sum();                       // 21
let doubled: Vec<i32> = v.iter().map(|x| x * 2).collect();
let big: Vec<i32> = v.iter().filter(|x| **x > 3).copied().collect();
  • map(|x| ...) transforms each item.
  • filter(|x| ...) keeps items for which the closure returns true. The closure receives a reference to the item, and iter() already yields references, so you often see **x (or copied() first to drop one level).
  • copied() turns &i32 items into i32.
  • sum() adds everything up. collect() gathers items into a collection, and the type annotation tells it which one.

Adapters are lazy: nothing runs until a consumer like sum or collect asks for items.

Strings work too: text.split_whitespace() is an iterator of words, and s.to_uppercase() returns a new String.

Your task

Everything must be pub. Use iterator chains rather than manual loops.

  1. pub fn sum_of_squares(v: &[i32]) -> i32: the sum of each element squared.
  2. pub fn evens(v: &[i32]) -> Vec<i32>: only the even numbers, in the original order.
  3. pub fn shout_long_words(words: &[&str], min_len: usize) -> Vec<String>: keep the words whose length (in bytes) is at least min_len, and return them uppercased, in order.

Next lesson →

Sign in to run your code. It's free.