我如何应对惰性迭代器?

How do I cope with lazy iterators?

我正在尝试使用 map() 在迭代器上对数组进行排序。

struct A {
    b: Vec<B>,
}

#[derive(PartialEq, Eq, PartialOrd, Ord)]
struct B {
    c: Vec<i32>,
}

fn main() {
    let mut a = A { b: Vec::new() };

    let b = B { c: vec![5, 2, 3] };
    a.b.push(b);

    a.b.iter_mut().map(|b| b.c.sort());
}

给出警告:

warning: unused `std::iter::Map` that must be used
  --> src/main.rs:16:5
   |
16 |     a.b.iter_mut().map(|b| b.c.sort());
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: #[warn(unused_must_use)] on by default
   = note: iterators are lazy and do nothing unless consumed

没错,sort() 实际上并没有在这里调用。 book 中描述了此警告,但我不明白为什么 iter_mut() 的这种变体可以正常工作:

a.b.iter_mut().find(|b| b == b).map(|b| b.c.sort());

I don't understand why this variation with iter_mut() works fine:

a.b.iter_mut().find(|b| b == b).map(|b| b.c.sort());

之所以有效,是因为find不懒惰;它是一个迭代器消费者。它 return 是 Option 而不是 Iterator。这可能就是让您感到困惑的原因,因为 Option 也有一个 map 方法,这就是您在这里使用的方法。


正如其他人所说,map 用于转换数据,无需修改数据,也无需任何其他 side-effects。如果真的要用map,可以map over collection再赋值回去:

fn main() {
    let mut a = A { b: Vec::new() };
    let mut b = B { c: vec![5, 2, 3] };
    a.b.push(b);

    a.b =
        a.b.into_iter()
            .map(|mut b| {
                b.c.sort();
                b
            })
            .collect();
}

请注意向量的 sort 方法 returns (),因此您必须显式 return 来自映射函数的排序向量。

正如您链接到的那本书所说:

If you are trying to execute a closure on an iterator for its side effects, use for instead.

这样就可以了,任何阅读代码的人都清楚得多。当你想将一个向量转换为另一个向量时,你应该使用 map

我用for_each。 根据文档:

It is equivalent to using a for loop on the iterator, although break and continue are not possible from a closure. It's generally more idiomatic to use a for loop, but for_each may be more legible when processing items at the end of longer iterator chains. In some cases for_each may also be faster than a loop, because it will use internal iteration on adaptors like Chain.