use std::rc::Rc;
fn f1(cb: Box<Fn(i32) -> i32>) {
let res = cb(15);
println!("res {}", res);
}
fn main() {
let mut v2 = Rc::new(5_i32);
// 1
// f1(Box::new(move |x: i32| *v2 + x));
// 2
f1(Box::new(move |x: i32| {
let tmp = *v2;
*Rc::get_mut(&mut v2).unwrap() = tmp + 1;
x + *v2
}));
}
引用为“1”的代码,如果取消注释,编译并运行得很好,但引用为“2”的代码无法编译,失败并显示消息:
error[E0596]: cannot borrow `v2` as mutable, as it is a captured variable in a `Fn` closure
如果我想保持代码结构,我该如何解决这个问题呢?
在我的真实代码中,我想要连接两个特征。其中一个将调用事件的回调,另一个具有处理回调的函数:
trait Foo {
fn add_callback(&mut self, cb: Box<Fn(i32)>);
}
trait Boo {
fn on_new_data(&mut self, data: i32);
}
我想用Boo
创建一个特征对象,用Rc
包裹它,然后以Foo::add_callback
|x:i32| Rc::get_mut(&mut boo).unwrap().on_new_data(x)
答案 0 :(得分:3)
整个错误消息主要是有用:
error[E0596]: cannot borrow `v2` as mutable, as it is a captured variable in a `Fn` closure
--> src/main.rs:17:19
|
17 | *Rc::get_mut(&mut v2).unwrap() = tmp + 1;
| ^^^^^^^ cannot borrow as mutable
|
help: consider changing this to accept closures that implement `FnMut`
--> src/main.rs:15:17
|
15 | f1(Box::new(move |x: i32| {
| _________________^
16 | | let tmp = *v2;
17 | | *Rc::get_mut(&mut v2).unwrap() = tmp + 1;
18 | | x + *v2
19 | | }));
| |_____^
将f1
更改为接受FnMut
并使变量可变允许代码编译:
fn f1(mut cb: Box<FnMut(i32) -> i32>) {
为了将v2
参数所需的捕获变量&mut v2
变为Rc::get_mut
,需要这样做。