【问题标题】:How to update self based on reference of value from hashmap from self如何根据来自self的hashmap的值引用来更新self
【发布时间】:2017-05-23 18:08:48
【问题描述】:
use std::collections::HashMap;
use std::collections::hash_map::Entry::*;

struct A {
    map: HashMap<String, String>,
    i: i32
}
impl A {
    fn test(&mut self) {
        match self.map.get("abc") {
            None => {},
            Some(x) => self.trigger(&x)
        }
    }

    fn trigger(&mut self, x: &str) {
        self.i += 1;
    }
}

代码不起作用,因为self.trigger 可变地借用了self,而self.map.get 在范围内保留了self 的不可变借用。

鉴于我可以确保在trigger 中我不会修改self.map,有什么方法可以让它工作吗?

我不能让trigger 借用self 不变,就像Can I borrow self immutably for self.callbacks: Vec<Box<FnMut>>? 一样

我正在使用 rustc 1.19.0-nightly。

【问题讨论】:

    标签: rust


    【解决方案1】:

    这里的问题是借用检查器不知道trigger 只更改self.i。据借用检查器所知,它也可能更改self.map,这将是不安全的。

    解决方案是告诉借用检查器更多关于trigger 更改的信息。

    一种方法是将trigger 需要可变借用的所有内容移动到其自己的结构中,然后为该结构实现触发器:

    use std::collections::HashMap;
    use std::collections::hash_map::Entry::*;
    
    struct TriggerThing {
        i: i32
    }
    
    impl TriggerThing {
        fn trigger(&mut self, _: &HashMap<String, String>, x: &str) {
            self.i += 1;
        }
    }
    
    struct A {
        map: HashMap<String, String>,
        trigger_thing: TriggerThing,
    }
    
    impl A {
        fn test(&mut self) {
            // Its fine to have a immutable borrow of self.map
            // and a mutable borrow of self.trigger_thing at the
            // same time, since borrowing self.trigger_thing does not
            // imply a mutable borrow of self.map.
            if let Some(x) = self.map.get("abc") {
                // Notice that we can still give self.trigger_thing
                // access to self.map, as long as we only
                // give it an immutable reference
                self.trigger_thing.trigger(&self.map, &x)
            }
        }
    }
    

    如果您以前没有见过很棒的if let 语法,请参阅Rust Book: If Let

    【讨论】:

      猜你喜欢
      • 2013-03-08
      • 1970-01-01
      • 2021-08-15
      • 1970-01-01
      • 1970-01-01
      • 2012-05-04
      • 1970-01-01
      • 2012-04-09
      • 2020-09-06
      相关资源
      最近更新 更多