qed
qed

Reputation: 23134

Why does the closure for `take_while` take its argument by reference?

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?

Upvotes: 5

Views: 1111

Answers (1)

Shepmaster
Shepmaster

Reputation: 431489

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!

Upvotes: 4

Related Questions