实现 Iterator 时出现 Rust 类型错误
Rust type error when implementing Iterator
我正在尝试将 .split
从切片概括为迭代器,但我似乎无法获得正确的类型。这部分是因为我对 Rust 不是很有经验,部分是因为错误消息对于我从 Rust 看到的内容来说非常模糊。我已经包含了我认为是相关片段的内容,但还有一个特征 Splittable
及其实现。错误(我相信第二个错误是由第一个错误引起的,如果不正确请告诉我):
struct Split<I: Iterator, P: Fn(&I::Item) -> bool> {
iter: I,
pred: P,
}
impl<I: Iterator, P: Fn(&I::Item) -> bool> Iterator for Split<I, P> {
type Item = Vec<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
self.iter
.cloned()
.position(|x| (self.pred)(&x))
.map(|i| self.iter.take(i))
}
}
error[E0271]: type mismatch resolving `<I as std::iter::Iterator>::Item == &_`
--> src/main.rs:13:14
|
13 | .cloned()
| ^^^^^^ expected associated type, found reference
|
= note: expected associated type `<I as std::iter::Iterator>::Item`
found reference `&_`
= note: consider constraining the associated type `<I as std::iter::Iterator>::Item` to `&_` or calling a method that returns `<I as std::iter::Iterator>::Item`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error[E0599]: no method named `position` found for struct `std::iter::Cloned<I>` in the current scope
--> src/main.rs:14:14
|
14 | .position(|x| (self.pred)(&x))
| ^^^^^^^^ method not found in `std::iter::Cloned<I>`
|
= note: the method `position` exists but the following trait bounds were not satisfied:
`<I as std::iter::Iterator>::Item = &_`
which is required by `std::iter::Cloned<I>: std::iter::Iterator`
您收到的特定错误消息是 little misleading. What it is really complaining about is that std::slice::cloned
需要对引用进行迭代,您可以从其定义中看到:
fn cloned<'a, T>(self) -> Cloned<Self>
where
Self: Iterator<Item = &'a T>,
T: 'a + Clone,
它需要一个对实现 Clone
的项的引用的迭代器(并且描述指出它对于将 &T 上的迭代器转换为 T 上的迭代器很有用)。
但是,我怀疑您不是在尝试克隆正在迭代的项目,而是在尝试克隆迭代器本身。为此,您将使用 clone
方法,而不是 cloned
,并且您必须添加一个边界以确保迭代器是可克隆的,如下所示:
struct Split<I, P>
where
I: Iterator + Clone,
P: Fn(&I::Item) -> bool
您的代码中还有一些其他问题:
- 您正在多次借用
self
,以访问 iter
和 pred
。
- 您正在有效地将
self.iter
移动到 map
内的闭包中
take
消耗了你调用它的迭代器,所以即使你重构来避免上述两个问题,它仍然不会编译。
如果您确实打算将您的实现限制为基于引用的迭代器,您可以这样定义边界:
struct Split<'a, I, T, P>
where
I: Iterator<Item=&'a T>,
T: 'a + Clone,
P: Fn(&I::Item) -> bool
那么你就可以使用cloned
.
我正在尝试将 .split
从切片概括为迭代器,但我似乎无法获得正确的类型。这部分是因为我对 Rust 不是很有经验,部分是因为错误消息对于我从 Rust 看到的内容来说非常模糊。我已经包含了我认为是相关片段的内容,但还有一个特征 Splittable
及其实现。错误(我相信第二个错误是由第一个错误引起的,如果不正确请告诉我):
struct Split<I: Iterator, P: Fn(&I::Item) -> bool> {
iter: I,
pred: P,
}
impl<I: Iterator, P: Fn(&I::Item) -> bool> Iterator for Split<I, P> {
type Item = Vec<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
self.iter
.cloned()
.position(|x| (self.pred)(&x))
.map(|i| self.iter.take(i))
}
}
error[E0271]: type mismatch resolving `<I as std::iter::Iterator>::Item == &_`
--> src/main.rs:13:14
|
13 | .cloned()
| ^^^^^^ expected associated type, found reference
|
= note: expected associated type `<I as std::iter::Iterator>::Item`
found reference `&_`
= note: consider constraining the associated type `<I as std::iter::Iterator>::Item` to `&_` or calling a method that returns `<I as std::iter::Iterator>::Item`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
error[E0599]: no method named `position` found for struct `std::iter::Cloned<I>` in the current scope
--> src/main.rs:14:14
|
14 | .position(|x| (self.pred)(&x))
| ^^^^^^^^ method not found in `std::iter::Cloned<I>`
|
= note: the method `position` exists but the following trait bounds were not satisfied:
`<I as std::iter::Iterator>::Item = &_`
which is required by `std::iter::Cloned<I>: std::iter::Iterator`
您收到的特定错误消息是 little misleading. What it is really complaining about is that std::slice::cloned
需要对引用进行迭代,您可以从其定义中看到:
fn cloned<'a, T>(self) -> Cloned<Self>
where
Self: Iterator<Item = &'a T>,
T: 'a + Clone,
它需要一个对实现 Clone
的项的引用的迭代器(并且描述指出它对于将 &T 上的迭代器转换为 T 上的迭代器很有用)。
但是,我怀疑您不是在尝试克隆正在迭代的项目,而是在尝试克隆迭代器本身。为此,您将使用 clone
方法,而不是 cloned
,并且您必须添加一个边界以确保迭代器是可克隆的,如下所示:
struct Split<I, P>
where
I: Iterator + Clone,
P: Fn(&I::Item) -> bool
您的代码中还有一些其他问题:
- 您正在多次借用
self
,以访问iter
和pred
。 - 您正在有效地将
self.iter
移动到map
内的闭包中
take
消耗了你调用它的迭代器,所以即使你重构来避免上述两个问题,它仍然不会编译。
如果您确实打算将您的实现限制为基于引用的迭代器,您可以这样定义边界:
struct Split<'a, I, T, P>
where
I: Iterator<Item=&'a T>,
T: 'a + Clone,
P: Fn(&I::Item) -> bool
那么你就可以使用cloned
.