CodeBlanks Logo Icon CodeBlanks

Closure and iterator

Use closures with iterator methods.

Closures and iterators

The most common use of closures is iterator methods. Since a closure can capture values from its environment, the criteria can be given from outside:

let esik = 50;
let notlar = vec![45, 72, 90, 38, 66];
let gecen: Vec<i32> = notlar
    .iter()
    .copied()
    .filter(|&n| n >= esik)     // esik was captured
    .collect();
println!("{:?}", gecen);       // [72, 90, 66]

copied() turns &i32 elements into i32, so the following closures don't deal with double references.

Passing a function directly

Instead of a closure, a named function or method can be passed too; this shortens the code:

fn cift_mi(n: &i32) -> bool { n % 2 == 0 }

let v = vec![1, 2, 3, 4];
let ciftler: Vec<&i32> = v.iter().filter(|n| cift_mi(n)).collect();
let metinler: Vec<String> = v.iter().map(ToString::to_string).collect();
println!("{:?} {:?}", ciftler, metinler);   // [2, 4] ["1", "2", "3", "4"]

Practice Passing grades

For let esik = 50; and vec![45, 72, 90, 38, 66], collect the grades passing the threshold with filter. Then build a second vector with a map adding 5 to each. Print both vectors separated by a space.

Starter code

main.rs
fn main() {
    // buraya yaz
}

Sample solution

main.rs
fn main() {
    let esik = 50;
    let notlar = vec![45, 72, 90, 38, 66];
    let gecen: Vec<i32> = notlar.iter().copied().filter(|&n| n >= esik).collect();
    let artirilmis: Vec<i32> = gecen.iter().map(|n| n + 5).collect();
    println!("{:?} {:?}", gecen, artirilmis);
}

Expected output

[72, 90, 66] [77, 95, 71]

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Inside <code>.filter(|n| *n &gt; 2)</code>, why is <code>n</code> a reference?

  • All closure parameters are references
  • It's a bug
  • Only for i32
  • filter gives &Item to look at the element without consuming it Correct answer

Explanation: filter only looks at the element to keep or drop it, so it borrows. Combined with .iter() it becomes &&i32.

2 Filter by a criterion

Question
let gecen: Vec<i32> = notlar.iter().copied().____(|&n| n >= esik).collect();
Answer
let gecen: Vec<i32> = notlar.iter().copied().filter(|&n| n >= esik).collect();

Explanation: filter keeps the elements for which the closure returns true.

3 Method and closure role

Term Meaning
map(|x| ..) Transforms
filter(|x| ..) Filters
find(|x| ..) First match
any(|x| ..) At least one?

All lessons in Intermediate