rust - 将闭包传递给需要 std::ops::Fn 的函数

标签 rust closures traits

<分区>

我正在尝试使用闭包来调用一组特征向量上的函数。这里最重要的代码行是第一行,我们在这里说什么类型 query必须是最后一行,我们尝试在此结束。

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)));
}

当我运行它时,出现错误:

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]`

我以为闭包implemented Fn (或 FnOnceFnMut )?当您期望 Fn 时,提供闭包是否无效? ?我假设我需要指定关于 Fn 的其他内容在第一行?但是什么?

我假设我错误地指定了 query: Fn(&Vec<i32>) -> f64 的类型我的第一个函数的参数,或者闭包写错了|ref fv| my_query(fv, 3) .

我读了Passing closure to trait method: expected type parameter, found closure ,但这似乎更多地是关于传递一个不是函数接受的唯一类型的闭包。

最佳答案

第二个错误是更重要的错误:

error[E0277]: the trait bound `for<'r> std::ops::Fn(&'r std::vec::Vec<i32>) -> f64 + 'static: std::marker::Sized` is not satisfied

简而言之:Fn(&Vec<i32>) -> f64不是大小类型,不能按值传递。你只能通过trait objects (引用或框),或实现特征的(大小)类型的值。在这种情况下,您可能需要后者:

Playground

fn stat_query<F>(dataset: &Vec<Vec<i32>>, query: F) -> f64
where
    F: Fn(&Vec<i32>) -> 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::<f64>() / (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::<i32>() > threshold {
            1.
        } else {
            0.
        }
    }

    // run query on dataset with threshold 3
    println!("{}", stat_query(&my_dataset, |ref fv| my_query(fv, 3)));
}

关于rust - 将闭包传递给需要 std::ops::Fn 的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47295884/

相关文章:

reference - 遍历迭代器并改变值是否会更改集合中的值?

vector - 同时可变访问保证不相交的大向量的任意索引

rust - 使用 actix-web 代理流式传输大文件时如何防止超时问题?

rust - 如何在闭包和函数之间传递参数?

python - 将嵌套的 HasTraits 属性添加到 TraitsUI TView

c++ - 使用特征类时出错。 : "expected constructor destructor or type conversion before ' &' token"

c - 将 Rust 与 C 链接 : undefined reference to '__aeabi' functions

javascript - 设置要与 jquery click 函数一起使用的变量

ios - 将 block 形式的 objective-c 解决为 swift 3

groovy - 在 Groovy 中扩展类和实现 trait 有什么区别?