snippetrustMajor
How do I write an iterator that returns references to itself?
Viewed 0 times
howreturnswriteiteratoritselfthatreferences
Problem
I am having trouble expressing the lifetime of the return value of an
It is obvious that I am not using the lifetime parameter correctly but after trying various ways I just gave up, I have no idea what to do with it.
(Playground link)
--> src/main.rs:23:22
|
23 | type Item = Vec
Iterator implementation. How can I compile this code without changing the return value of the iterator? I'd like it to return a vector of references.It is obvious that I am not using the lifetime parameter correctly but after trying various ways I just gave up, I have no idea what to do with it.
use std::iter::Iterator;
struct PermutationIterator {
vs: Vec>,
is: Vec,
}
impl PermutationIterator {
fn new() -> PermutationIterator {
PermutationIterator {
vs: vec![],
is: vec![],
}
}
fn add(&mut self, v: Vec) {
self.vs.push(v);
self.is.push(0);
}
}
impl Iterator for PermutationIterator {
type Item = Vec;
fn next(&mut self) -> Option> {
'outer: loop {
for i in 0..self.vs.len() {
if self.is[i] >= self.vs[i].len() {
if i == 0 {
return None; // we are done
}
self.is[i] = 0;
self.is[i - 1] += 1;
continue 'outer;
}
}
let mut result = vec![];
for i in 0..self.vs.len() {
let index = self.is[i];
result.push(self.vs[i].get(index).unwrap());
}
*self.is.last_mut().unwrap() += 1;
return Some(result);
}
}
}
fn main() {
let v1: Vec = (1..3).collect();
let v2: Vec = (3..5).collect();
let v3: Vec = (1..6).collect();
let mut i = PermutationIterator::new();
i.add(v1);
i.add(v2);
i.add(v3);
loop {
match i.next() {
Some(v) => {
println!("{:?}", v);
}
None => {
break;
}
}
}
}(Playground link)
error[E0261]: use of undeclared lifetime name 'a`--> src/main.rs:23:22
|
23 | type Item = Vec
Solution
As far as I understand, you want want the iterator to return a vector of references into itself, right? Unfortunately, it is not possible in Rust.
This is the trimmed down
Note that there is no lifetime connection between
except that this is not a valid
Such iterators (the ones which can return references into themselves) are called streaming iterators. You can find more here, here and here, if you want.
Update. However, you can return a reference to some other structure from your iterator - that's how most of collection iterators work. It could look like this:
Note how lifetime
This is the trimmed down
Iterator trait:trait Iterator {
type Item;
fn next(&mut self) -> Option;
}
Note that there is no lifetime connection between
&mut self and Option. This means that next() method can't return references into the iterator itself. You just can't express a lifetime of the returned references. This is basically the reason that you couldn't find a way to specify the correct lifetime - it would've looked like this:fn next(&'a mut self) -> Option>
except that this is not a valid
next() method for Iterator trait.Such iterators (the ones which can return references into themselves) are called streaming iterators. You can find more here, here and here, if you want.
Update. However, you can return a reference to some other structure from your iterator - that's how most of collection iterators work. It could look like this:
pub struct PermutationIterator {
vs: &'a [Vec],
is: Vec
}
impl Iterator for PermutationIterator {
type Item = Vec;
fn next(&mut self) -> Option> {
...
}
}
Note how lifetime
'a is now declared on impl block. It is OK to do so (required, in fact) because you need to specify the lifetime parameter on the structure. Then you can use the same 'a both in Item and in next() return type. Again, that's how most of collection iterators work.Context
Stack Overflow Q#30422177, score: 53
Revisions (0)
No revisions yet.