Hello. I need help understanding the purpose of GAT. The "lending iterator" use case comes up a lot on google searches. I am going through this official tutorial to help me understand it.
It proposes this hypothetical trait definition:
trait Iterable {
// Type of item yielded up; will be a reference into `Self`.
type Item;
// Type of iterator we return. Will return `Self::Item` elements.
type Iter: Iterator<Item = Self::Item>;
fn iter<'c>(&'c self) -> Self::Iter;
}
and it claims,
"The fact that the lifetime parameter
'c
is declared on the method is not just a minor detail. It is exactly what allows something to be iterated many times"
It goes on to say that this trait could not be implemented as the associated types will not be able to declare the right lifetime, hence the need for GAT.
However, I seem to have written a working example, one that can be iterated multiple times, without GAT?
fn main() {
let nums = vec![4, 5, 6];
count_twice(&nums);
}
struct Iter<'c, T> {
data: &'c [T],
}
impl<'c, T> Iterator for Iter<'c, T> {
type Item = &'c T;
fn next(&mut self) -> Option<Self::Item> {
if let Some((prefix_elem, suffix)) = self.data.split_first() {
self.data = suffix;
Some(prefix_elem)
} else {
None
}
}
}
trait Iterable<'c> {
type Item;
type Iter: Iterator<Item = Self::Item>;
fn iter(&'c self) -> Self::Iter;
}
impl<'c, T: 'c> Iterable<'c> for Vec<T> {
type Item = &'c T;
type Iter = Iter<'c, T>;
fn iter(&'c self) -> Self::Iter {
Iter { data: self }
}
}
fn count_twice<'c, I: Iterable<'c, Item = &'c i32>>(iterable: &'c I) {
let mut count = 0;
for _ in iterable.iter() {
count += 1;
}
for i in iterable.iter() {
process(*i, count);
}
}
fn process(i: i32, count: i32) {
println!("{}", i / count);
}
I'm sure I'm misunderstanding. There must be some manner in which my example is worse than the GAT implementation from the official tutorial, but I am unable to see it. Please help!