我怎样才能在 Rust 中实现这样的目标
struct TestStruct {
map:HashMap<String, Box<FnMut(i32) -> ()>>,
val:i32
}
impl TestStruct {
fn new() -> Self {
let mut ts = TestStruct{ map: Default::default(), val: 0 };
ts.map.insert(String::from("add"),Box::new(|a| ts.val+=a ));
ts.map.insert(String::from("mult"),Box::new(|a| ts.val*=a ));
ts
}
fn execute(&mut self, cmd:&str,arg:i32) {
let f = self.map.get_mut(cmd).unwrap();
f(arg);
}
}
这显然行不通,因为
ts
被多次借用
解决方案真的这么难看吗?
impl TestStruct {
fn new() -> Self {
let mut map:HashMap<String, Box<Fn(i32) -> ()>> = HashMap::new();
let val = Rc::new(RefCell::new(0));
let v1 = val.clone();
map.insert(String::from("add"),Box::new(move |a|
{
let mut mutator = v1.borrow_mut();
*mutator+=a;
}
));
let v1 = val.clone();
map.insert(String::from("mult"),Box::new(move |a| {
{
let mut mutator = v1.borrow_mut();
*mutator*=a;
}
}
));
TestStruct{ map, val }
}
fn execute(&mut self, cmd:&str,arg:i32) {
let f = self.map.get_mut(cmd).unwrap();
f(arg);
}
}
有没有一种方法可以用完全不同的方法来实现这样的目标?
我建议避免共享可变性,除非绝对必要。在这种情况下,您只能在函数执行时通过传递
val
作为可变引用参数来为其提供可变引用:
use std::collections::HashMap;
struct TestStruct {
map: HashMap<String, Box<dyn FnMut(&mut i32, i32) -> ()>>,
val: i32
}
impl TestStruct {
fn new() -> Self {
let mut ts = TestStruct { map: Default::default(), val: 0 };
ts.map.insert(String::from("add"), Box::new(|val, a| *val += a ));
ts.map.insert(String::from("mult"), Box::new(|val, a| *val *= a ));
ts
}
fn execute(&mut self, cmd: &str, arg: i32) {
let f = self.map.get_mut(cmd).unwrap();
f(&mut self.val, arg);
}
}