wpadłem na problem, który upraszcza się, co następuje:Czy mogę napisać Iterator, który sam się mutuje, a następnie zwraca się do siebie?
struct MyIter {
vec: Vec<i8>,
}
fn fill_with_useful_data(v: &mut Vec<i8>) {
/* ... */
}
impl<'a> Iterator for MyIter {
type Item = &'a [i8];
fn next(&mut self) -> Option<&'a [i8]> {
fill_with_useful_data(&mut self.vec);
Some(&self.vec)
}
}
fn main() {
for slice in (MyIter { vec: Vec::new() }) {
println!("{}", slice);
}
}
ten generuje błąd:
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
--> src/main.rs:9:6
|
9 | impl<'a> Iterator for MyIter {
| ^^ unconstrained lifetime parameter
Chodzi o to, że iterator robi kilka prac, które odzwierciedla w swoich dziedzinach i na każdy krok, daje w sobie odniesienie do kodu wywołującego. W tym przypadku mógłbym go modelować jako dostarczający kopię stanu zamiast odniesienia, ale udawajmy, że nie jest to możliwe lub po prostu niewygodne.
Intuicyjnie to nie powinno być problemu, ponieważ kontroler pożyczyć może zapewnić, że .next()
nie nazywa się ponownie, gdy uzyskano odniesienia może być nadal stosowany do kontroli stanu iterator, ale cecha Iterator
nie wydaje się przewidywać tego rodzaju rzeczy bezpośrednio. Nawet z pewnymi permutacjami, jak tylko utrzymywanie odniesienia do wektora w samym iteratorze lub uczynienie iteratora odniesieniem lub czymś, co spowoduje, że te wcielenia zostaną wcześniej wypieczone, nie mogę uzyskać niczego poza kontrolą wypożyczenia.
Przeczytałem na blogu "Iterators yielding mutable references", ale nie jestem pewien, czy/jak to dotyczy mojego problemu, który nie dotyczy zmiennych referencji.
W porządku, właśnie przestałem implementować 'Iterator' i stworzyłem własną pętlę for z makrem. Nie myślałem o tym, jak ".collect()" nie wyszło. – ben
Jest to również przydatne w przypadku przejazdów, w których nie można użyć pętli 'for': while while Some (element) = iter.next() {...' – bluss
Dla przyszłego odniesienia, ten typ iteratora ('fn next (& 'a self) ') jest często określany jako * iterator przesyłania strumieniowego *. Niektóre przykłady dyskusji [1] (https://users.rust-lang.org/t/returning-borrowed-values-from-an-iterator/1096), [2] (https://www.reddit.com/r/rust/comments/2t1rxx/more_general_iterator_trait /) i [skrzynia implementująca jego formę] (https://github.com/sfackler/streaming-iterator). – Shepmaster