链接不同类型的迭代器时会出现类型错误。
let s = Some(10);
let v = (1..5).chain(s.iter())
.collect::<Vec<_>>();
输出:
<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
但是在压缩时它可以正常工作:
let s = Some(10);
let v = (1..5).zip(s.iter())
.collect::<Vec<_>>();
输出:
[(1, 10)]
为什么Rust能够推断出zip
的正确类型而不是chain
的正确类型,我该如何解决?注:我希望能够为任何迭代器执行此操作,因此我不想要一个适用于Range和Option的解决方案。
答案 0 :(得分:10)
首先,请注意迭代器会产生不同的类型。我在数字中添加了一个明确的u8
,以使类型更明显:
fn main() {
let s = Some(10u8);
let r = (1..5u8);
let () = s.iter().next(); // Option<&u8>
let () = r.next(); // Option<u8>
}
当你chain
两个迭代器时,两个迭代器必须产生相同的类型。这是有道理的,因为迭代器无法“切换”当它到达一个结束并从第二个结束时它输出的类型:
fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter>
where U: IntoIterator<Item=Self::Item>
// ^~~~~~~~~~~~~~~ This means the types must match
为什么zip
有效?因为它没有这个限制:
fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter>
where U: IntoIterator
// ^~~~ Nothing here!
这是因为zip
返回一个元组,每个迭代器都有一个值;一种新类型,与源迭代器的类型不同。一个迭代器可以是整数类型,另一个可以为所有zip
关注返回自己的自定义类型。
为什么Rust能够推断出
zip
的正确类型,而不是chain
这里没有类型推断;那是另一回事。这只是普通的类型不匹配。
我该如何解决?
在这种情况下,你的内部迭代器产生一个对整数Clone
- 能力类型的引用,所以你可以使用cloned
创建一个新的迭代器来克隆每个值,然后两个迭代器都会具有相同的类型:
fn main() {
let s = Some(10);
let v: Vec<_> = (1..5).chain(s.iter().cloned()).collect();
}
如果您已完成该选项,您还可以使用使用迭代器和into_iter
:
fn main() {
let s = Some(10);
let v: Vec<_> = (1..5).chain(s.into_iter()).collect();
}