我试图找出为什么这不起作用(游乐场):
fn main() {
let a = vec![1, 2, 3, 4];
let b = a.clone();
// slice and iter (wrong way)
let s: i32 = &a[1..a.len()].iter()
.zip(&b[1..b.len()].iter())
.map(|(x, y)| x * y)
.sum();
println!("{}", s);
}错误:
rustc 1.13.0 (2c6933acc 2016-11-07)
error[E0277]: the trait bound `&std::slice::Iter<'_, {integer}>: std::iter::Iterator` is not satisfied
--> <anon>:6:10
|
6 | .zip(&b[1..b.len()].iter())
| ^^^ trait `&std::slice::Iter<'_, {integer}>: std::iter::Iterator` not satisfied
|
= note: `&std::slice::Iter<'_, {integer}>` is not an iterator; maybe try calling `.iter()` or a similar method
= note: required because of the requirements on the impl of `std::iter::IntoIterator` for `&std::slice::Iter<'_, {integer}>`
error: no method named `map` found for type `std::iter::Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>` in the current scope
--> <anon>:7:10
|
7 | .map(|(x, y)| x * y)
| ^^^
|
= note: the method `map` exists but the following trait bounds were not satisfied: `&std::slice::Iter<'_, {integer}> : std::iter::Iterator`, `std::iter::Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>> : std::iter::Iterator`但这确实有效:
fn main() {
let a = vec![1, 2, 3, 4];
let b = a.clone();
// slice and iter (correct way)
let s: i32 = a[1..a.len()].iter()
.zip(b[1..b.len()].iter())
.map(|(x, y)| x * y)
.sum();
println!("{}", s);
}请解释向量在锈蚀中是如何工作的,以及当我iter()时,上面的区别。
发布于 2016-12-09 13:41:00
简单地说,:您可能误解了操作符优先级:
&b[1..b.len()].iter()等于:
&(b[1..b.len()].iter())由于zip()期望实现IntoIterator,所以调用失败,因为对迭代器类型的引用不会实现上述特性。
充分解释
让我们试着理解错误信息!当然,我们首先看一下第一个错误:
error[E0277]: the trait bound `&std::slice::Iter<'_, {integer}>: std::iter::Iterator` is not satisfied
--> <anon>:6:10
|
6 | .zip(&b[1..b.len()].iter())
| ^^^ trait `&std::slice::Iter<'_, {integer}>: std::iter::Iterator` not satisfied
|
= note: `&std::slice::Iter<'_, {integer}>` is not an iterator; maybe try calling `.iter()` or a similar method
= note: required because of the requirements on the impl of `std::iter::IntoIterator` for `&std::slice::Iter<'_, {integer}>`哇,这可真够多的。但是我们可以看到,zip()的某些特性约束要求被违反了。那么,让我们看一下上述函数的签名:
fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter>
where U: IntoIterator重要的是other参数(U类型)。U必须是IntoIterator。这个特性被实现了很多类型..。让我们检查一下我们试图传递给zip()的类型
&b[1..b.len()].iter()要彻底地分析这个问题,我们需要了解一些东西,但我会试着把它分解。首先,让我们通过插入更多括号来消除操作符优先级的歧义。上面的代码片段相当于:
&(b[1..b.len()].iter())foo[bar] desugares为*::std::ops::Index::index(&foo, bar)。这是这里最复杂的部分,但是在文档中查找这个部分会发现表达式b[1..b.len()]具有[i32]类型。iter(),它返回一个类型Iter<_, _>,它是片的迭代器类型。&:你借用Iter<_, _>的东西,导致了&Iter<_, _>。这符合错误信息!看最后一个音符:
note: required because of the requirements on the impl of `std::iter::IntoIterator` for `&std::slice::Iter<'_, {integer}>`所以..。什么能满足IntoIterator的特性?首先,实现Iterator的每一种类型(例如Iter<_, _>)都实现了IntoIterator。因此,您只需删除表达式中的&,它就能工作了!
但是我们可以做得更好!IntoIterator也是为&[T]实现的,所以您也可以删除.iter(),这样就可以工作了!
工作守则
let s: i32 = a[1..].iter()
.zip(&b[1..])
.map(|(x, y)| x * y)
.sum();注意:我还删除了范围的上限,使其半开,如保罗·法拉贝拉所言。
发布于 2016-12-09 13:45:03
您的第一个版本有一个操作符优先的问题:&a[1..a.len()].iter()首先应用iter(),然后引用它,最后引用一个std::slice::Iter。
正如您在Iter上看到的那样,有一个用于Iter的impl Iterator,但没有针对&Iter的。这就是第一个错误想要说的:(看看上面写着:&std::slice::Iter<'_, {integer}>不是迭代器的部分)。
简化一下,您可以拥有:
fn main() {
let a = vec![1, 2, 3, 4];
// let b = a.clone(); // no more need to clone. We're going to only
// work with references
let s: i32 = (&a[1..]).iter() // you don't need the a.len()
// to slice to the end
.zip(&a[1..]) // &a implements IntoIter, which zip
// accepts, so you don't need iter()
.map(|(x, y)| x * y)
.sum();
println!("{}", s);
}发布于 2016-12-09 13:38:26
Iterator::zip需要一些实现IntoIterator的东西。
不是传递Iterator,而是传递对Iterator的引用。Iterator会发生变异,而引用是不够的。
您可以使用括号来解决这一问题,以明确您试图从
fn main() {
let a = vec![1, 2, 3, 4];
let b = a.clone();
let s: i32 = (&a)[1..a.len()].iter()
.zip(((&b)[1..b.len()]).iter())
.map(|(x, y)| x * y)
.sum();
println!("{}", s);
}https://stackoverflow.com/questions/41061165
复制相似问题