【问题标题】:Iteratively get mutable references of child nodes迭代获取子节点的可变引用
【发布时间】:2020-07-04 11:52:30
【问题描述】:

我需要一个类似assocPath的函数,我想确认某个子节点是否存在,如果存在,获取它的可变引用,如果不存在,创建并获取它。

我遇到了一些困难,我的父节点是可变引用,子节点也是可变引用,所以应该释放父节点的引用,但是编译器告诉我“不能两次赋值给不可变变量”,这让我很困惑。

以下是我的尝试,请问如何解决?

use std::collections::HashMap;

pub enum JsonValue {
    Null,
    Bool(bool),
    Number(f32),
    String(String),
    Array(Vec<JsonValue>),
    Object(HashMap<String, JsonValue>),
}

impl JsonValue {
    fn new() -> JsonValue { JsonValue::Object(HashMap::new()) }
    fn check_key_path(mut self, path: &str) -> &JsonValue {
        let ref mut node = self;
        for k in path.split(".") {
            match node {
                JsonValue::Object(dict) => {
                    node = match dict.get(k) {
                        Some(ref mut s) => s,
                        None => &mut dict.insert(k.to_string(), JsonValue::new()).unwrap()
                    }
                }
                _ => panic!("NotObject")
            }
        }
        node
    }
}

fn main() {
    let mut v = JsonValue::new();
    v.check_key_path("some.node.path");
}

【问题讨论】:

    标签: rust mutable


    【解决方案1】:

    这里有几个问题:

    • check_key_path 按值取 self,这意味着 self 被方法消耗。一旦self 被使用,您想从该方法返回的&amp;JsonValue 将被丢弃,因此引用无效。
    • let ref mut 声明了一个 immutable 绑定到一个可变 reference,这意味着您可以更改引用的数据,但不能更改绑定引用的数据。这是您在尝试重新分配 node 时看到的错误。
    • 你在调用dict.get(k)时将dict作为不可变借用,然后尝试dict.insert()(可变借用dict)。

    标准库提供了一个类型 Entry&lt;K, V&gt; 来帮助处理这类事情:您可以从 HashMap 获取一个值,或者如果 Entry::or_insert 不存在则创建它。

    这是更新后的代码的playground link,如下所示:

    // takes &mut self instead of mut self
    fn check_key_path(&mut self, path: &str) -> &JsonValue {
        // declare node as a mutable binding with value &mut self
        let mut node = self;
        for k in path.split(".") {
            match node {
                JsonValue::Object(dict) => {
                    // get or create value with key k
                    node = dict.entry(k.to_string()).or_insert(JsonValue::new());
                }
                _ => panic!("NotObject")
            }
        }
        node
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-20
      • 1970-01-01
      • 1970-01-01
      • 2016-06-10
      相关资源
      最近更新 更多