【问题标题】:Vec::iter() converts to borrow of OptionVec::iter() 转换为借用 Option
【发布时间】:2016-02-09 17:36:09
【问题描述】:

下面是我的代码中的一个简化示例,它读取目录、遍历文件并在每个文件的末尾附加注释...

这个例子显示了一个Vec<Option<bool>>,在调用iter()之后,编译器将Option<_>解释为借用&Option<_>类型。我想了解为什么我会看到这种行为。

fn main() {
    let vec = vec![Some(true), None];

    vec.iter()
        .filter_map(|o| o)
        .count();
}

编译器输出

src/main.rs:50:25: 50:26 error: mismatched types:
 expected `core::option::Option<_>`,
    found `&core::option::Option<bool>`
(expected enum `core::option::Option`,
    found &-ptr) [E0308]
src/main.rs:50         .filter_map(|o| o)

【问题讨论】:

    标签: rust


    【解决方案1】:

    Vec::iter 返回一个Iter 结构,它实现Iterator 为:

    impl<'a, T> Iterator for Iter<'a, T> {
        type Item = &'a T;
    }
    

    换句话说,每次调用Iterator::next返回的值的类型将是对向量中项目的引用。

    如果您更改为vec.into_iter(),您的代码可以正常工作:

    fn main() {
        let vec = vec![Some(true), None];
    
        vec.into_iter()
            .filter_map(|o| o)
            .count();
    }
    

    在这种情况下,您正在迭代一个以不同方式实现 IteratorIntoIter 结构,并返回对象本身:

    impl<T> Iterator for IntoIter<T> {
        type Item = T;
    }
    

    这是必需的,因为一次只有一个事物可能拥有每个矢量项。通常,您希望让向量拥有该项目并对引用进行操作。 into_iter 消耗向量,将整个向量的所有权转移到IntoIter 结构。然后允许该结构将每个项目的所有权授予filter_map 调用。

    如果您的类型实现了Clone,您还可以克隆每个项目。这允许向量保持所有权并创建一个新项目:

    fn main() {
        let vec = vec![Some(true), None];
    
        vec.iter()
            .cloned()
            .filter_map(|o| o)
            .count();
    }
    

    【讨论】:

      【解决方案2】:

      这个怎么样:

      fn main() {
          let my_vec = vec![Some(true), None];
      
          println!("{}", my_vec.iter().filter_map(|&x| x).count());
      }
      

      应用filter_map时,你可以将&amp;x映射到x,你的代码就可以工作了。

      正如@Shepmaster 在评论中指出的那样,这仅适用于实现Copy 的类型。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-23
        • 2021-03-16
        • 1970-01-01
        相关资源
        最近更新 更多