I'm trying to use a closure to call a function on a bunch of feature vectors. The most important code lines here are the first line, where we say what type query
must be and the last line, where we try to give a closure.
fn stat_query(dataset: &Vec<Vec<i32>>, query: Fn(&Vec<i32>) -> f64) -> f64 {
// takes in a dataset of feature vectors and a query,
// returns the average of the query on the dataset
if dataset.len() == 0 {
0.
} else {
dataset.iter().map(|ref fv| query(&fv)).sum() / (dataset.len() as f64)
}
}
fn main() {
// build dataset
let fv1: Vec<i32> = vec![1, 1, 1, 1, 1];
let fv2: Vec<i32> = vec![1, 0, 1, 0, 1];
let my_dataset = vec![fv1, fv2];
// query checks whether sum of features is greater than a threshold
fn my_query(ref fv: &Vec<i32>, threshold: i32) -> f64 {
if fv.iter().sum() > threshold {
1.
} else {
0.
}
}
// run query on dataset with threshold 3
println!("{}", stat_query(&my_dataset, |ref fv| my_query(fv, 3)));
}
When I run this, I get an error:
error[E0277]: the trait bound `for<'r> std::ops::Fn(&'r std::vec::Vec<i32>) -> f64 + 'static: std::marker::Sized` is not satisfied
--> src/main.rs:1:40
|
1 | fn stat_query(dataset: &Vec<Vec<i32>>, query: Fn(&Vec<i32>) -> f64) -> f64 {
| ^^^^^ `for<'r> std::ops::Fn(&'r std::vec::Vec<i32>) -> f64 + '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 std::vec::Vec<i32>) -> f64 + 'static`
= note: all local variables must have a statically known size
error[E0308]: mismatched types
--> src/main.rs:27:44
|
27 | println!("{}", stat_query(&my_dataset, |ref fv| my_query(fv, 3)));
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected trait std::ops::Fn, found closure
|
= note: expected type `for<'r> std::ops::Fn(&'r std::vec::Vec<i32>) -> f64 + 'static`
found type `[closure@src/main.rs:27:44: 27:68]`
I thought closures implemented Fn
(or FnOnce
or FnMut
)? Is it not valid to provide a closure when you expect a Fn
? I assume I need to specify something else about the Fn
in the first line? But what?
I assume I have incorrectly specified the type of either the query: Fn(&Vec<i32>) -> f64
parameter of my first function, or have written the closure wrong |ref fv| my_query(fv, 3)
.
I read Passing closure to trait method: expected type parameter, found closure, but that seems to be more about passing a closure that isn't the only kind of thing the function is accepting.