I want to build a function that splits a list into two: one list that contains the elements of the original list that satisfy a certain predicate, and another that contains
You should read the official Rust book, especially the chapter on closures. Your function declaration is incorrect; you are specifying that f
has a bare trait type, which is impossible; that's exactly what the error about Sized
is about. You should use a generic type parameter instead:
fn split_filter<T: Clone, F>(a: &[T], f: F) -> (Vec<T>, Vec<T>)
where
F: for<'a> Fn(&'a T) -> bool,
I have also changed the type of a
from &Vec<T>
to &[T]
; there is no situation in which you would prefer the former to the latter. &Vec<T>
is automatically coerced to &[T]
when necessary. See Why is it discouraged to accept a reference to a String (&String) or Vec (&Vec) as a function argument?
The second error is closely tied to the mistake in the function declaration; your original function declaration specified a bare trait type, but closures do not have this type, they just implement the function trait.
The final program looks like this:
fn split_filter<T: Clone, F>(a: &[T], f: F) -> (Vec<T>, Vec<T>)
where
F: Fn(&T) -> bool,
{
let mut i: Vec<T> = vec![];
let mut e: Vec<T> = vec![];
for u in a.iter().cloned() {
if f(&u) {
i.push(u);
} else {
e.push(u);
}
}
return (i, e);
}
fn main() {
let v = vec![10, 40, 30, 20, 60, 50];
println!("{:?}", split_filter(&v, |&a| a % 3 == 0));
}
Try it on the playground.