应对延迟迭代器

时间:2016-01-13 11:50:15

标签: rust monads

我正在尝试使用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 result which must be used:
iterator adaptors are lazy and do nothing unless consumed, 
#[warn(unused_must_use)] on by default

这是真的,sort()实际上并未在这里调用。 book中描述了此警告, 但我真的不明白为什么它以iter_mut()a.b.iter_mut() .find(|b| b == b) .map(|b| b.c.sort()); 的方式工作 为什么这种变化很好:

post

3 个答案:

答案 0 :(得分:5)

正如您链接的书所说:&#34;如果您尝试在迭代器上执行闭包以获得其副作用,请改用for。&#34;

这种方式有效,对于阅读代码的人来说,它更加清晰。如果您希望&#34;转换&#34;您应该使用map一个不同的向量。

答案 1 :(得分:3)

  

我真的不明白为什么iter_mut()以这种方式工作以及为什么这种变化可以正常工作

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

它有效,因为find不是懒惰的;它是一个迭代器消费者。它会返回Option而不是Iterator。这可能是令您感到困惑的原因,因为Option也有map方法,这就是您在此处使用的方法。

正如其他人所说,map旨在转换数据,而无需修改数据,也没有任何其他副作用。如果您真的想使用map,可以映射集合并将其分配回来:

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

请注意,vector的sort方法返回(),因此您必须从映射函数显式返回已排序的向量。

答案 2 :(得分:0)

我使用for_each。 根据文档:

  

这等效于在迭代器上使用for循环,尽管breakcontinue从闭包中是不可能的。使用for循环通常更惯用,但是在较长的迭代器链末尾处理项目时,for_each可能更易读。在某些情况下,for_each也可能比循环更快,因为它会在Chain之类的适配器上使用内部迭代。