Trying to filter a set of items, based on a predicate that is generic, because computed at run-time:
fn main () {
let el = vec![
vec![10, 20, 30],
vec![40, 50, 60]
];
println!("{:?}", use_predicate(el, a_predicate)); // [[40, 50, 60]]
}
fn a_predicate(it: &mut impl Iterator<Item = u64>) -> bool {
it.any(|n| n > 50)
}
pub fn use_predicate<I: Iterator<Item = u64>>(
items: Vec<Vec<u32>>,
predicate: impl FnMut(&mut I) -> bool
) -> Vec<Vec<u32>> {
items
.into_iter()
// ISSUE HERE
//
// If I collect and rewrite predicate as predicat(Vec<u64>), it works,
// however I want to avoid allocation just to iterate over the elements.
//
// It also works if I just call `a_predicate` directly, but I need to
// pass the predicate as a parameter...
//
// In other words, the error doesn't happen unless I have nested generics.
.filter(|it| predicate(&mut it.iter().map(|it| *it as u64)))
.collect::<Vec<_>>()
}
The compilation error indicate that rustc is not able to consider the u64
iterator as a impl Iterator<Item = u64>
.
error[E0308]: mismatched types
--> src/main.rs:25:32
|
10 | pub fn use_predicate<I: Iterator<Item = u64>>(
| - this type parameter
...
25 | .filter(|it| predicate(&mut it.iter().map(|it| *it as u64)))
| --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `I`, found struct `Map`
| |
| arguments to this function are incorrect
|
= note: expected mutable reference `&mut I`
found mutable reference `&mut Map<std::slice::Iter<'_, u32>, [closure@src/main.rs:25:51: 25:55]>`
I am not sure how to restrict the type while avoiding to collect into a Vec<_>
, which is useless cost, since we only need to iterate over the items in order to filter.
EDIT: Using dyn
as suggested below is not an undesirable solution, as I'm sure is still much faster than collecting into a heap allocated Vec<_>
. However, in production, I am facing a lifetime issue that is difficult to solve without wrapping the predicate: FnMut
in a Mutex
, and unlocking each time a predicate must be evaluated. And at this point, I am not so optimistic about the performance outlook.
I made another playground to better represent the issue. Here's the issue being solved by wrapping in an Arc<Mutex<_>>
.
Can you think of a way to solve this without making use of the Mutex
?