我想构建一个将列表拆分为两个的函数:一个列表包含原始列表中满足某个谓词的元素,另一个列表包含所有不满足某个谓词的元素.以下是我的尝试:
fn split_filter<T: Clone + Sized>(a: &Vec<T>, f: Fn(&T) -> bool) -> (Vec<T>, Vec<T>) {
let i: Vec<T> = vec![];
let 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));
}
Run Code Online (Sandbox Code Playgroud)
但是,我收到两个错误:
error[E0277]: the trait bound `for<'r> std::ops::Fn(&'r T) -> bool + 'static: std::marker::Sized` is not satisfied
--> src/main.rs:1:47
|
1 | fn split_filter<T: Clone + Sized>(a: &Vec<T>, f: Fn(&T) -> bool) -> (Vec<T>, Vec<T>) {
| ^ `for<'r> std::ops::Fn(&'r T) -> bool + 'static` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `for<'r> std::ops::Fn(&'r T) -> bool + 'static`
= note: all local variables must have a statically known size
error[E0308]: mismatched types
--> src/main.rs:17:39
|
17 | println!("{:?}", split_filter(&v, |&a| a % 3 == 0));
| ^^^^^^^^^^^^^^^ expected trait std::ops::Fn, found closure
|
= note: expected type `for<'r> std::ops::Fn(&'r {integer}) -> bool + 'static`
found type `[closure@src/main.rs:17:39: 17:54]`
Run Code Online (Sandbox Code Playgroud)
第二个错误似乎意味着闭包不是一个Fn.我尝试使用f: |&T| -> bool我在网上找到的语法,但这似乎不适用于最新版本的Rust.
至于第一个错误,我曾希望T Sized制作它会使函数具有已知的大小,但显然它没有.
Vla*_*eev 17
你应该阅读正式的Rust书,特别是有关闭包的章节.你的函数声明不正确; 你指定的是f具有裸特征类型,这是不可能的; 这正是错误的关键Sized所在.您应该使用泛型类型参数:
fn split_filter<T: Clone, F>(a: &[T], f: F) -> (Vec<T>, Vec<T>)
where
F: for<'a> Fn(&'a T) -> bool,
Run Code Online (Sandbox Code Playgroud)
我也改变类型a从&Vec<T>到&[T]; 没有哪种情况你更喜欢前者和后者.必要时&Vec<T>会自动强制执行&[T].请参阅为什么不鼓励接受对String(&String)或Vec(&Vec)的引用作为函数参数?
第二个错误与函数声明中的错误密切相关; 你的原始函数声明指定了一个裸特征类型,但是闭包没有这种类型,它们只是实现了函数特征.
最终的程序如下所示:
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));
}
Run Code Online (Sandbox Code Playgroud)
在操场上试试吧.