I am trying to figure out why this does not work (Playground):
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);
}
Error:
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`
But this does work:
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);
}
Please explain how vectors work in Rust and the difference above when I iter()
.
答案 0 :(得分:15)
简而言之:您可能误解了运算符优先级:
&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}>`
哇,这真是一口气。但是我们可以看到function 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]
脱离*::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();
注意:我还删除了范围的上限,使它们半开,as Paolo Falabella suggested。
答案 1 :(得分:5)
您的第一个版本存在运算符优先级问题: -c, --close close connection on EOF from stdin
首先应用&a[1..a.len()].iter()
,然后引用它,以对iter()
的引用结束。
正如您在docs for Iter
上看到的那样,std::slice::Iter
有impl Iterator
但Iter
没有&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);
}
答案 2 :(得分:2)
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);
}