闭包不会捕获参数

Closure won't capture argument

我是 Rust 的初学者,我从教程中拿了一个例子并决定尝试一下。 Cacher 中的函数 fn new 没有看到第二个参数,这里是闭包,我试图传递 |num,num2|。我不知道我做错了什么。我们使用一个参数

struct Cacher<T>

where
T: Fn(u32) -> u32,
{
    calculation: T,
    value: Option<u32>,
    multiplication : T,
}



impl<T> Cacher<T>
where
    T:  Fn(u32) -> u32,
{   
    fn new(calculation: T, multiplication : T) -> Cacher<T> {
        Cacher {
            calculation,
            value: None, 
            multiplication,
        }
    }
fn generate_workout(intensity: u32, random_number: u32, test_test_multiplication: u32,) {
    let mut expensive_result = Cacher::new( |num,num2|  {
        println!("calculating slowly...");
        thread::sleep(Duration::from_secs(2));
        num + num2
    });

这里是错误

error[E0061]: this function takes 2 arguments but 1 argument was supplied
  --> src/main.rs:43:32
   |
43 |       let mut expensive_result = Cacher::new( |num,num2|  {
   |  ________________________________^^^^^^^^^^^__-
   | |                                |
   | |                                expected 2 arguments
44 | |         println!("calculating slowly...");
45 | |         thread::sleep(Duration::from_secs(2));
46 | |         num + num2
47 | |     });
   | |_____- supplied 1 argument
   |
note: associated function defined here
  --> src/main.rs:21:8
   |
21 |     fn new(calculation: T, multiplication : T) -> Cacher<T> {

UPD 最后我找到了带括号的语法解释:

About round brackets in 'let v = (self.calculation)(arg);'

您的闭包类型被声明为采用一个 u32 参数和 return 一个 u32 值:

Fn(u32) -> u32

但是您提供的闭包接受两个 个参数。这表明应该更改闭包类型以指定闭包应该接受两个参数:

Fn(u32, u32) -> u32

此外,Cacher::new()声明接受两个这样的闭包,但你只传递一个。

然而,当你解决这个问题时,你将 运行 陷入另一个问题:两个参数都被声明为相同的类型 (T),但是每个闭包都有自己不同的类型,所以这个签名要求您两次传递完全相同的闭包类型,这可能不是您想要的。

您需要引入第二个泛型类型参数:

struct Cacher<T, U>
where
    T: Fn(u32, u32) -> u32,
    U: Fn(u32, u32) -> u32,
{
    calculation: T,
    value: Option<u32>,
    multiplication : U,
}

impl<T, U> Cacher<T, U>
where
    T:  Fn(u32, u32) -> u32,
    U:  Fn(u32, u32) -> u32,
{   
    fn new(calculation: T, multiplication : U) -> Cacher<T, U> {
        // ...

随着这变得越来越复杂,如果您使用盒装闭包,可能会更容易维护和推理您的代码,由于间接堆分配和动态调度,它有一个小的 运行时间性能损失,但可能值得不必为这么多类型而烦恼:

struct Cacher
{
    calculation: Box<dyn Fn(u32, u32) -> u32>,
    value: Option<u32>,
    multiplication : Box<dyn Fn(u32, u32) -> u32>,
}

impl Cacher
{   
    fn new(
        calculation: impl Fn(u32, u32) -> u32,
        multiplication : impl Fn(u32, u32) -> u32
    ) -> Cacher {
        Cacher {
            calculation: Box::new(calculation),
            value: None, 
            multiplication: Box::new(multiplication),
        }
    }
    // ...