-
-
Save rylev/3a3dd4b0d8563eb2267f489e559bb70e to your computer and use it in GitHub Desktop.
struct MyIterator<'a, T> { | |
slice: &'a [T], | |
} | |
impl<'a, T> Iterator for MyIterator<'a, T> { | |
type Item = &'a T; | |
fn next<'next>(&'next mut self) -> Option<Self::Item> { | |
let (element, rest) = self.slice.split_first()?; | |
self.slice = rest; | |
Some(element) | |
// let element = self.slice.get(0); | |
// self.slice = &self.slice[1..]; | |
// element | |
} | |
} | |
struct MyMutableIterator<'iter, T> { | |
slice: &'iter mut [T], | |
} | |
impl<'iter, T> Iterator for MyMutableIterator<'iter, T> { | |
type Item = &'iter mut T; | |
fn next<'next>(&'next mut self) -> Option<Self::Item> { | |
let slice1 = &mut self.slice; | |
let slice2 = std::mem::replace(slice1, &mut []); | |
let (first, rest) = slice2.split_first_mut()?; | |
self.slice = rest; | |
Some(first) | |
// // get first element | |
// let element = self.slice.get_mut(0); | |
// // set self.slice to the rest of the list | |
// self.slice = &mut self.slice[1..]; | |
// // return first element | |
// element | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
#[test] | |
fn it_works() { | |
let mut collection = vec![1, 2, 3, 4]; | |
let wrapper = MyIterator { | |
slice: &collection[..], | |
}; | |
for (index, elem) in wrapper.enumerate() { | |
assert_eq!(*elem, collection[index]); | |
} | |
let mut collection = vec![1, 2, 3, 4]; | |
let wrapper = MyMutableIterator { | |
slice: &mut collection[..], | |
}; | |
for (index, elem) in wrapper.enumerate() { | |
*elem = *elem + 1; | |
} | |
assert_eq!(collection.get(0), Some(&2)); | |
} | |
} |
Reading through the docs for
std::mem::replace
it states, thatBut replace can be used to disassociate the original value at that index from self, allowing it to be returned:
. So I have one question left to understand the code: In https://gist.github.com/rylev/3a3dd4b0d8563eb2267f489e559bb70e#file-iterator-rs-L27, what lifetime does the compiler thinkslice2
has? It's not'next
because we are disassociated fromself
. And why does it think that new lifetime is longer than'next
. Best would be in plain English 😄
The lifetime is 'a
, that's the reason why this piece of code does the trick. let slice2 = std::mem::replace(slice1, &mut []);
says - Instead of borrowing slice, I want to own it temporarily
I think the below simplification is easier to understand the key point of this gist (and tested to work):
fn next(&mut self) -> Option<Self::Item> {
let owned_slice_including_lifetime = std::mem::take(&mut self.slice);
let (first, rest) = owned_slice_including_lifetime.split_first_mut()?;
self.slice = rest;
Some(first)
}
Reading through the docs for
std::mem::replace
it states, thatBut replace can be used to disassociate the original value at that index from self, allowing it to be returned:
. So I have one question left to understand the code:In https://gist.github.com/rylev/3a3dd4b0d8563eb2267f489e559bb70e#file-iterator-rs-L27, what lifetime does the compiler think
slice2
has? It's not'next
because we are disassociated fromself
. And why does it think that new lifetime is longer than'next
. Best would be in plain English 😄