闭包参数:传递一个改变内部变量的函数

Closure arguments: passing a function that mutates the inner variables

想法是要有一个闭包(change_x 在这种情况下)捕获状态(x 在这种情况下)将函数作为其参数(alterer)这将决定如何内部状态改变。

pub fn plus17(h: & u64) -> u64 {
    *h + 17
}

pub fn main() {
    let x = 0; //take x by reference

    let mut change_x = move |alterer: &dyn FnOnce(&u64) ->u64 |  alterer(&x) ;
    change_x(&mut plus17);

    println!("{}", x);
}

但是我似乎无法正确选择类型:

error[E0161]: cannot move a value of type dyn for<'r> FnOnce(&'r u64) -> u64: the size of dyn for<'r> FnOnce(&'r u64) -> u64 cannot be statically determined
  --> playground/src/main.rs:19:69
   |
19 |     let mut increment_x = move |alterer: &dyn FnOnce(&u64) ->u64 |  alterer(&x) ;
   |                                                                     ^^^^^^^

error[E0507]: cannot move out of `*alterer` which is behind a shared reference
  --> playground/src/main.rs:19:69
   |
19 |     let mut increment_x = move |alterer: &dyn FnOnce(&u64) ->u64 |  alterer(&x) ;
   |                                                                     ^^^^^^^ move occurs because `*alterer` has type `dyn for<'r> FnOnce(&'r u64) -> u64`, which does not implement the `Copy` trait

我不确定我是否有理由将 dyn 放在我放的地方,这是编译器的建议,我不太确定为什么我必须把它放在那里。是因为尽管 &u64->u64 的 input/return 类型,alterer 可以是任意大小吗?

我也曾尝试将 alterer 设为 FnMut 而不是 FnOnce,但我对它们的区别以及给定的 alterer 会 运行只有一次(在外部闭包调用的那一刻change_x)似乎是合理的。

FnOnce 需要一个拥有的 self。因此 alterer 不能是 FnOnce,因为它不是拥有的而是引用。

您可以选择 &dyn Fn&mut dyn FnMut(我建议选择 FnMut),或者选择 Box<dyn FnOnce>.