How do I cope with lazy iterators?

风格不统一 提交于 2019-12-19 10:23:20

问题


I'm trying to sort an array with a map() over an iterator.

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());
}

Gives the warning:

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

Which is true, sort() isn't actually called here. This warning is described in the book, but 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());

回答1:


As the book you linked to says:

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

That way it works, and it's much clearer to anyone reading the code. You should use map when you want to transform a vector to a different one.




回答2:


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());

It works because find is not lazy; it's an iterator consumer. It returns an Option not an Iterator. This might be why it is confusing you, because Option also has a map method, which is what you are using here.


As others have said, map is intended for transforming data, without modifying it and without any other side-effects. If you really want to use map, you can map over the collection and assign it back:

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();
}

Note that vector's sort method returns (), so you have to explicitly return the sorted vector from the mapping function.




回答3:


I use for_each. According to the doc:

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.



来源:https://stackoverflow.com/questions/34765967/how-do-i-cope-with-lazy-iterators

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!