我想编写一个以闭包为参数的函数,该函数以另一个闭包为参数,如下所示:

fn test<F: Fn(G), G: Fn()>(f: F) {
    let print = || {
        println!("hello");
    };
    f(print);
}

fn main() {
    test(|print| {
        print();
    })
}

但这会给出以下错误:

error[E0308]: mismatched types
 --> src/main.rs:5:7
  |
1 | fn test<F: Fn(G), G: Fn()>(f: F) {
  |                   - expected this type parameter
2 |     let print = || {
  |                 -- the found closure
...
5 |     f(print);
  |     - ^^^^^ expected type parameter `G`, found closure
  |     |
  |     arguments to this function are incorrect
  |
  = note: expected type parameter `G`
                    found closure `{closure@src/main.rs:2:17: 2:19}`

推荐答案

fn test<F: Fn(G), G: Fn()>(f: F)

这是这样的:"testf: F,其中F是取Gspecific函数类型,Gspecific函数类型".但是您不希望F接受调用者 Select 的特定函数类型.您希望F接受any个可调用函数.

原则上,你want要说的是这样的.

fn test<F: ∀(G: Fn()) => Fn(G)>(f: F)

当然,我在这里虚构了语法,但您想说的是"对于all个函数类型G,F可以接受G并做一些有用的事情".铁 rust 不是Rank-2 polymorphism,所以我们需要找到一个变通办法.

首先,您可以只需支付间接成本,然后获取特征对象.

fn test<F: Fn(Box<dyn Fn()>)>(f: F) {
  let print = || {
    println!("hello");
  };
  f(Box::new(print));
}

您已经将"我不知道G是什么"问题从编译 timeshift 到了运行时,并且只是将信息抛到了vtable中.这是可行的,它不会改变从main调用函数的方式,但它确实需要在运行时进行虚拟查找,这对性能有很小的影响.

由于您的闭包是not捕获(至少在本例中不是这样),您也可以只在第二级获取一个函数指针.

fn test<F: Fn(fn())>(f: F) {
  let print = || {
    println!("hello");
  };
  f(print);
}

请注意内部的小写字母fn().这是一台function pointer type fn,notimmutable callable object trait Fn.

这就限制了你的内部函数(print)要么是普通的fn,要么是非捕获闭包,这对你的用例来说已经足够好了.

Rust相关问答推荐

基于对vec值的引用从该值中删除该值

为什么对不可复制数据的引用的取消引用没有O权限来避免Rust中的双重释放?

在没有引用计数或互斥锁的情况下,可以从Rust回调函数内的封闭作用域访问变量吗?

为什么`Vec i64`的和不知道是`Option i64`?

为什么std repeat trait绑定在impl块和关联函数之间?

铁 rust 中的泛型:不能将`<;T作为添加>;::Output`除以`{Float}`

`Pin`有没有不涉及不安全代码的目的?

为什么Rust不支持带关联常量的特征对象?

什么是`&;[][..]`铁 rust 里的刻薄?

为什么我必须使用 PhantomData?在这种情况下它在做什么?

从 rust 函数返回 &HashMap

通过写入 std::io::stdout() 输出不可见

通过mem::transmute将数组展平安全吗?

Rust typestate 模式:实现多个状态?

TcpStream::connect - 匹配武器具有不兼容的类型

火箭整流罩、tokio-scheduler 和 cron 的生命周期问题

Rustfmt 是否有明确类型的选项?

如何从 many0 传播 Nom 失败上下文?

传递 Option<&mut T> 时何时需要 mut

Rust 生命周期:不能在方法内重新borrow 可变字段