I'm attempting to store a series of entries inside a Vec. Later I need to reprocess through the Vec to fill in some information in each entry about the next entry. The minimal example would be something like this:
struct Entry {
curr: i32,
next: Option<i32>
}
struct History {
entries: Vec<Entry>
}
where I would like to fill in the next
fields to the next entries' curr
value. To achieve this, I want to make use of the tuple_windows
function from Itertools on the mutable iterator. I expect I can write a function like this:
impl History {
fn fill_next_with_itertools(&mut self) {
for (a, b) in self.entries.iter_mut().tuple_windows() {
a.next = Some(b.curr);
}
}
}
However, it refuse to compile because the iterator Item
's type, &mut Entry
, is not Clone
, which is required by tuple_windows
function. I understand there is a way to iterate through the list using the indices like this:
fn fill_next_with_index(&mut self) {
for i in 0..(self.entries.len()-1) {
self.entries[i].next = Some(self.entries[i+1].curr);
}
}
But I feel the itertools' approach more natural and elegant. What's the best ways to achieve the same effect?
From the documentation:
tuple_window
clones the iterator elements so that they can be part of successive windows, this makes it most suited for iterators of references and other values that are cheap to copy.
This means that if you were to implement it with &mut
items, then you'd have multiple mutable references to the same thing which is undefined behaviour.
If you still need shared, mutable access you'd have to wrap it in Rc<RefCell<T>>
, Arc<Mutex<T>>
or something similar:
fn fill_next_with_itertools(&mut self) {
for (a, b) in self
.entries
.iter_mut()
.map(RefCell::new)
.map(Rc::new)
.tuple_windows()
{
a.borrow_mut().next = Some(b.borrow().curr);
}
}