结构成员(HashMap)中的闭包捕获对另一个结构成员的可变引用

问题描述 投票:0回答:1

我怎样才能在 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);
    }
}

有没有一种方法可以用完全不同的方法来实现这样的目标?

rust closures
1个回答
0
投票

我建议避免共享可变性,除非绝对必要。在这种情况下,您只能在函数执行时通过传递

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);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.