我试图弄清楚为什么这不起作用(游乐场):
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);
}
Run Code Online (Sandbox Code Playgroud)
错误:
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`
Run Code Online (Sandbox Code Playgroud)
但这确实有效:
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);
}
Run Code Online (Sandbox Code Playgroud)
请解释一下Rust中的矢量如何工作以及上面的差异iter().
Luk*_*odt 15
简而言之:您可能误解了运算符优先级:
&b[1..b.len()].iter()
Run Code Online (Sandbox Code Playgroud)
等于:
&(b[1..b.len()].iter())
Run Code Online (Sandbox Code Playgroud)
并且由于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}>`
Run Code Online (Sandbox Code Playgroud)
哇,这真是一口气.但是我们可以看到违反了函数的zip()某些特征约束要求.那么,让我们来看看所述函数的签名:
fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter>
where U: IntoIterator
Run Code Online (Sandbox Code Playgroud)
重要的是other论证(类型U).U必须是IntoIterator.这个特性实现了很多类型......让我们检查一下我们尝试传递的类型zip():
&b[1..b.len()].iter()
Run Code Online (Sandbox Code Playgroud)
要完全分析这个,我们需要了解一些东西,但我会尝试将其分解.首先,让我们通过插入更多括号来消除运算符优先级的歧义.上面的代码片段相当于:
&(b[1..b.len()].iter())
Run Code Online (Sandbox Code Playgroud)
一种表达方式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}>`
Run Code Online (Sandbox Code Playgroud)
那么......满足这个IntoIterator特质的是什么?例如,实现Iterator(例如Iter<_, _>)的每种类型也实现IntoIterator.所以你可以删除&表达式,它的工作原理!
但我们可以做得更好!IntoIterator也实现了&[T],所以你也可以删除它.iter(),它的工作原理!
let s: i32 = a[1..].iter()
.zip(&b[1..])
.map(|(x, y)| x * y)
.sum();
Run Code Online (Sandbox Code Playgroud)
注意:我也删除了范围的上限以使它们半开,正如Paolo Falabella建议的那样.
您的第一个版本存在运算符优先级问题:首先&a[1..a.len()].iter()应用iter()然后引用它,以对a的引用结束std::slice::Iter.
正如你可以在看文档的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);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1766 次 |
| 最近记录: |