I have a slice of items and a slice of indices into the first slice, essentially giving me a sub-group of items that I want to modify. To iterate over the items and manipulate them I can create the following helper function.
fn process_things_by_index_loop<T>(things: &mut [T], indices: &[usize], f: &dyn Fn(&mut T)) {
for &ix in indices {
let t = &mut things[ix];
f(t);
}
}
This works fine, but I would actually just like to get an iterator over the items so I can apply, e.g., a filter to them before further processing.
It looks like this could just be a mapping of indices to items like so:
fn iterate_thigns<'a, T>(
things: &'a mut [T],
indices: &'a [usize],
) -> impl Iterator<Item = &'a mut T> {
indices.iter().map(|&ix| -> &mut T { &mut things[ix] })
}
This can't work of course, since I could have the same index twice in the indices slice and when collecting the iterator I would create two mutable references to the same item. So this gives appropriately a life-time error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src\main.rs:4:47
|
4 | indices.iter().map(|&ix|-> &mut T { &mut things[ix]})
| ^^^^^^^^^^
|
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src\main.rs:4:47
|
4 | indices.iter().map(|&ix|-> &mut T { &mut things[ix]})
| ^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 4:24...
--> src\main.rs:4:24
|
4 | indices.iter().map(|&ix|-> &mut T { &mut things[ix]})
| ^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src\main.rs:4:47
|
4 | indices.iter().map(|&ix|-> &mut T { &mut things[ix]})
| ^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the function body at 3:19...
--> src\main.rs:3:19
|
3 | fn iterate_thigns<'a, T>(things: &'a mut [T], indices: &'a [usize]) -> impl Iterator<Item=&'a mut T>{
| ^^
= note: ...so that the types are compatible:
expected &mut T
found &'a mut T
This also means the return type probably can't be a simple Iterator
at all.
This issues seems also related to this blog post from 2013 on "Iterators yielding mutable references", which states that no standard solutions for this pattern exist yet.
There is also a related question asking about mutable multi threaded access to the content of a vector, but I am really interested in a single threaded, iterator-like solution, which might even allow indices to repeat.
So, is there something that enables an iterator-like interface for sequential iteration of the items indicated by the indices?