Vec :: iter()转换为借用Option

时间:2016-02-09 17:36:10

标签: rust

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

此示例显示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)

2 个答案:

答案 0 :(得分:4)

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

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

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

答案 1 :(得分:1)

这个怎么样:

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

    println!("{}", my_vec.iter().filter_map(|&x| x).count());
}

应用filter_map后,您可以将&x映射到x,您的代码就可以使用。

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