链接不同类型的迭代器

Pet*_*all 2 iterator rust

链接不同类型的迭代器时出现类型错误.

let s = Some(10);
let v = (1..5).chain(s.iter())
        .collect::<Vec<_>>();
Run Code Online (Sandbox Code Playgroud)

输出:

<anon>:23:20: 23:35 error: type mismatch resolving `<core::option::Iter<'_, _> as core::iter::IntoIterator>::Item == _`:
 expected &-ptr,
    found integral variable [E0271]
<anon>:23     let v = (1..5).chain(s.iter())
                             ^~~~~~~~~~~~~~~
<anon>:23:20: 23:35 help: see the detailed explanation for E0271
<anon>:24:14: 24:33 error: no method named `collect` found for type `core::iter::Chain<core::ops::Range<_>, core::option::Iter<'_, _>>` in the current scope
<anon>:24             .collect::<Vec<_>>();
                       ^~~~~~~~~~~~~~~~~~~
<anon>:24:14: 24:33 note: the method `collect` exists but the following trait bounds were not satisfied: `core::iter::Chain<core::ops::Range<_>, core::option::Iter<'_, _>> : core::iter::Iterator`
error: aborting due to 2 previous errors
Run Code Online (Sandbox Code Playgroud)

但是在压缩时它工作正常:

let s = Some(10);
let v = (1..5).zip(s.iter())
        .collect::<Vec<_>>();
Run Code Online (Sandbox Code Playgroud)

输出:

[(1, 10)]
Run Code Online (Sandbox Code Playgroud)

为什么Rust能够推断出正确的类型zip但不是为了chain我能如何修复它?我希望能够为任何迭代器执行此操作,因此我不想要一个仅适用于Range和Option的解决方案.

She*_*ter 10

首先,请注意迭代器产生不同的类型.我已经添加了一个明确u8的数字,使类型更明显:

fn main() {
    let s = Some(10u8);
    let r = (1..5u8);

    let () = s.iter().next(); // Option<&u8>
    let () = r.next();        // Option<u8>
}
Run Code Online (Sandbox Code Playgroud)

当你有chain两个迭代器时,两个迭代器必须产生相同的类型.这是有道理的,因为迭代器无法"切换"它到达一个结束时输出的类型,并从第二个开始:

fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter> 
    where U: IntoIterator<Item=Self::Item>
//                        ^~~~~~~~~~~~~~~ This means the types must match
Run Code Online (Sandbox Code Playgroud)

那为什么要zip工作?因为它没有这个限制:

fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter> 
    where U: IntoIterator
//                       ^~~~ Nothing here!
Run Code Online (Sandbox Code Playgroud)

这是因为zip从每个迭代器返回一个带有一个值的元组; 一种新类型,与源迭代器的类型不同.一个迭代器可以是一个整数类型,另一个可以为所有zip关注返回您自己的自定义类型.

为什么Rust能够推断出正确的类型,zip但不能推断出chain

这里没有类型推断; 那是另一回事.这只是普通的类型不匹配.

我该如何解决?

在这种情况下,你的内部迭代器产生一个整数,一个Clone-able类型的引用,所以你可以cloned用来创建一个克隆每个值的新迭代器,然后两个迭代器都有相同的类型:

fn main() {
    let s = Some(10);
    let v: Vec<_> = (1..5).chain(s.iter().cloned()).collect();
}
Run Code Online (Sandbox Code Playgroud)

如果您正在使用的选项来完成,你也可以使用一个耗时的迭代器具有into_iter:

fn main() {
    let s = Some(10);
    let v: Vec<_> = (1..5).chain(s.into_iter()).collect();
}
Run Code Online (Sandbox Code Playgroud)