4

Here is an example from Rust by Example:

fn is_odd(n: u32) -> bool {
    n % 2 == 1
}

fn main() {
    println!("Find the sum of all the squared odd numbers under 1000");
    let upper = 1000;

    // Functional approach
    let sum_of_squared_odd_numbers: u32 =
        (0..).map(|n| n * n)             // All natural numbers squared
             .take_while(|&n| n < upper) // Below upper limit
             .filter(|n| is_odd(*n))     // That are odd
             .fold(0, |sum, i| sum + i); // Sum them
    println!("functional style: {}", sum_of_squared_odd_numbers);
}

Why does the closure for take_while take its argument by reference, while all the others take by value?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
qed
  • 22,298
  • 21
  • 125
  • 196
  • 2
    Both take_while and filter receive a reference. In this example, in take_while the reference is destructured with |&n|, and in filter the reference is dereferenced with *n. – A.B. Mar 25 '16 at 14:32

1 Answers1

4

The implementation of Iterator::take_while is quite illuminating:

fn next(&mut self) -> Option<I::Item> {
    if self.flag {
        None
    } else {
        self.iter.next().and_then(|x| {
            if (self.predicate)(&x) {
                Some(x)
            } else {
                self.flag = true;
                None
            }
        })
    }
}

If the value returned from the underlying iterator were directly passed to the predicate, then ownership of the value would also be transferred. After the predicate was called, there would no longer be a value to return from the TakeWhile adapter if the predicate were true!

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366