struct Data {
v: Vec<i32>,
}
impl Iterator for Data {
type Item = &[i32];
fn next(&mut self)->Option<Self::Item> {
let mut a = 0;
let mut b = 0;
// after some actions ...
Some(&self.v[a..b])
}
}
fn main() {}
The above code is to do some actions, and returns a slice from the next function. However, after doing some fixes based on the error hints, I still have not find a right method.
The compiling error is as follows:
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> src/main.rs:6:17
|
6 | type Item = &[i32];
| ^ explicit lifetime name needed here
The code replied can solve the problem, which give me a new light. And there are some other scenarios for example,
struct Data<I:Iterator> {
i: I,
v: Vec<<I as Iterator>::Item>,
}
impl<I:Iterator> Iterator for Data<I> {
type Item = &[<I as Iterator>::Item]; // fixed from &<I as Iterator>::Item
fn next(&mut self)->Option<Self::Item> {
// after some action ...
// for example, we can record the value selected
let v = self.i.next()?;
self.v.push(v);
// ...
let v = self.i.next()?;
self.v.push(v);
Some(self.v.as_slice())
}
}
Errors below:
12 | type Item = &[<I as Iterator>::Item];
| ^ explicit lifetime name needed here
However, if I use the DataIter instead, another issue arises,
struct DataIter<'a,I:Iterator> {
i: I,
v: &'a [<I as Iterator>::Item],
}
impl<'a,I:Iterator> Iterator for DataIter<'a,I> {
type Item = &'a [<I as Iterator>::Item]; // fixed from &'a <I as Iterator>::Item
fn next(&mut self) -> Option<Self::Item> {
// some action, for example
// here, how do we record the item into self.v?
let v = self.i.next()?;
self.v.push(v);
Some(self.v)
}
}
impl<'a,I:Iterator> IntoIterator for &'a Data<I> {
type Item = &'a [<I as Iterator>::Item];
type IntoIter = DataIter<'a,I>;
fn into_iter(self) -> Self::IntoIter {
DataIter {
i: self.i,
v: self.v.as_slice(),
}
}
}
Errors below:
|
31 | self.v.push(v);
| ^^^^ method not found in `&[<I as Iterator>::Item]
As shown, encountering different issues in two scenarios.
Your latest examples are somewhat confused. However, one underlying theme is this:
So there is no[1] world where the Iterator implementor collects the results of some other iterator into itself, and then returns a reference (&_) to them. The specific errors you get in attempting to do this don't really matter; it's just not possible, so you need a different design.
You could return the same item as the nested iterator (I::Item, not &'_ I::Item).
You could return something with shared ownership (e.g. Arc<I::Item>) and store it in the implementing type as well, but it would be pretty non-idiomatic (unusual, weird).
OMG, Sorry, I made a mistake and have the code at two places fixed in the implementing body.
1st, in Data<>'s body, the type Item fixed into a slice.
2nd, in DataIter<>'s body, the type item fixed into a slice too.
The main function of the code is to store the item value from the inner iterator that meets a certain condition and then return slice of these stored item with each calling of function next()
The Iterator trait guarantees that this code is valid:
let a = iter.next()?;
let b = iter.next()?;
drop(iter);
use_both(a, b);
If dropping your iterator would invalidate any of the previously returned values, you can't use the Iterator trait, and even a million lifetime bounds won't solve that problem.
If you return a reference to self.v, then dropping the iterator would invalidate returned self.v references (Rust doesn't have a GC, so it can't make any reference live longer). You also can't modify self.v any more after it's been given out as shared/immutable.
Thanks, guys. All your replies has deeply helped me understand the lifetime design of Iterator. I rethink the problem, and maybe I should find another way to solve it.
You could do something with internal iteration (taking a closure to call instead of implementing Iterator). One option would be something like this, which lets the user do whatever calculation they need on the slice as long as their return value doesn't borrow from it:
struct Data<I:Iterator> {
i: I,
v: Vec<<I as Iterator>::Item>,
}
impl<I:Iterator> Data<I> {
pub fn map_slice<O>(mut self, mut f:impl FnMut(&[I::Item])->O)->impl Iterator<Item=O> {
std::iter::from_fn(move || {
// after some action ...
// for example, we can record the value selected
let v = self.i.next()?;
self.v.push(v);
// ...
let v = self.i.next()?;
self.v.push(v);
Some(f(self.v.as_slice()))
})
}
}