我想构建一个将列表拆分为两个的函数:一个列表包含原始列表中满足某个谓词的元素,另一个列表包含所有不满足某个谓词的元素。以下是我的尝试:
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));
}
但是,我收到两个错误:
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]`
第二个错误似乎暗示闭包不是Fn
。我尝试使用我在网上找到的语法f: |&T| -> bool
,但这似乎不适用于最新版本的Rust。
至于第一个错误,我原本希望制作T
Sized
以使函数具有已知大小,但显然它不会。
答案 0 :(得分:16)
你应该阅读正式的Rust书,特别是the chapter on closures。你的函数声明不正确;你指定/**
* Sets the background for a view while preserving its current padding. If the background drawable
* has its own padding, that padding will be added to the current padding.
*
* @param view View to receive the new background.
* @param backgroundDrawable Drawable to set as new background.
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@SuppressWarnings("deprecation")
public static void setBackgroundAndKeepPadding(View view, Drawable backgroundDrawable) {
Rect drawablePadding = new Rect();
backgroundDrawable.getPadding(drawablePadding);
int top = view.getPaddingTop() + drawablePadding.top;
int left = view.getPaddingLeft() + drawablePadding.left;
int right = view.getPaddingRight() + drawablePadding.right;
int bottom = view.getPaddingBottom() + drawablePadding.bottom;
int sdk = android.os.Build.VERSION.SDK_INT;
if(sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
view.setBackgroundDrawable(backgroundDrawable);
} else {
view.setBackground(backgroundDrawable);
}
view.setPadding(left, top, right, bottom);
}
有一个特殊的特征类型,这是不可能的;这正是f
的错误所在。您应该使用泛型类型参数:
Sized
我还将fn split_filter<T: Clone, F>(a: &[T], f: F) -> (Vec<T>, Vec<T>)
where
F: for<'a> Fn(&'a T) -> bool,
的类型从a
更改为&Vec<T>
;没有哪种情况你更喜欢前者和后者。必要时,&[T]
会自动强制转为&Vec<T>
。见Why is it discouraged to accept a reference to a String (&String) or Vec (&Vec) as a function argument?
第二个错误与函数声明中的错误密切相关;你的原始函数声明指定了一个裸特征类型,但是闭包没有这种类型,它们只是实现了函数特性。
最终的计划如下:
&[T]
在playground上尝试。