Start learning free

LESSON 104 OF 348 · ARRAYS I

Vec and Iterators in Rust in Rust

Lesson

The everyday list type in Rust is Vec — a growable array that owns its elements. The quickest way to build one is the vec! macro, and because Vec has no plain {} formatting, you print the whole thing with the debug placeholder {:?}:

let nums = vec![10, 20, 30];
println!("{:?}", nums);    // prints [10, 20, 30]

You could process a list with an index loop like for i in 0..nums.len() — it compiles, but it's not how Rust is written. Idiomatic code uses iterators: .iter() borrows each element in turn (the vector stays alive and usable afterwards), and you chain adapters onto it. .map(|x| ...) transforms every element, .filter(|x| ...) keeps only the ones that pass a test, .sum() reduces everything to one number, and .collect() gathers results into a new Vec:

let doubled: Vec<i32> = nums.iter().map(|x| x * 2).collect();

The trap:

.collect() can build many different containers — a Vec, a HashSet, even a String — so the compiler must be told which one you want. Every beginner eventually leaves the annotation off, and compilation stops with this exact error:

error[E0283]: type annotations needed
 --> src/main.rs:3:9
  |
3 |     let squares = nums.iter().map(|x| x * x).collect();
  |         ^^^^^^^                              ------- type must be known at this point
  |
  = note: cannot satisfy `_: FromIterator<i32>`
help: consider giving `squares` an explicit type
  |
3 |     let squares: Vec<_> = nums.iter().map(|x| x * x).collect();
  |                ++++++++

The help: line hands you the fix: annotate the binding, e.g. let squares: Vec<i32> = .... The same rule applies to .sum() — write let sum: i32 = ... so it knows which number type to produce.


Two closure details worth knowing:

Because .iter() only borrows, the closure in filter receives a reference — write *x to dereference it before doing arithmetic like *x % 2 == 0. And when you want the kept values as owned numbers rather than references, add .cloned() before .collect(): it copies each surviving &i32 into a plain i32.


Assignment
Follow the Coding Tutorial to process one list three ways, without a single index variable:

  • Build nums as the vector [1, 2, 3, 4, 5] with the vec! macro.
  • Use .iter().map(...).collect() to build squares, and print it with {:?}.
  • Use .iter().sum() to compute sum, and print it.
  • Use .iter().filter(...).cloned().collect() to build evens, and print it with {:?}.

The exact expected output is:

squares = [1, 4, 9, 16, 25]
sum = 15
evens = [2, 4]

Hint
If the compiler says type annotations needed, give the binding an explicit type: : Vec<i32> for a collect, : i32 for a sum. If it complains inside the filter closure, remember the element arrives as a reference — dereference it with *x.


STEP 1 OF 7
    Ctrl + Enter to check

    Vec And Iterators in Rust

    Keep going with RustAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free