Rust 检索树值的可变引用

Rust 检索树值的可变引用,rust,mutable,Rust,Mutable,披露:这是我的Rust编程课的一个家庭作业问题。我也在努力理解/学习这些材料 因此,我有一个类似于以下内容的树(包含更改): 为了保持对当前节点的可变引用,在搜索每个树/子树的子树时,我在Vec上使用iter\u mut(): for child in current_node.children.iter_mut() { ... } 找到正确的节点后,从中提取值并返回: let val_opt: Option<&mut V> = current_node.val.as_

披露:这是我的Rust编程课的一个家庭作业问题。我也在努力理解/学习这些材料

因此,我有一个类似于以下内容的树(包含更改):

为了保持对
当前节点的可变引用
,在搜索每个树/子树的子树时,我在
Vec
上使用
iter\u mut()

for child in current_node.children.iter_mut() {
  ...
}
找到正确的节点后,从中提取值并返回:

let val_opt: Option<&mut V> = current_node.val.as_mut();
return match val_opt {
  Some(val) => {
    return Some(val)
  },
  None => None
}
我试图理解为什么会发生这种情况,以及我如何克服它。从基本的搜索来看,这似乎与生命周期有关,但我对如何补救这一问题有些茫然。此外,我无法更改
结构或函数签名

最小实现:

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Tree<V> {
    val: Option<V>,
    children: Vec<(char, Tree<V>)>,
}

fn str_split_first(x: &str) -> Option<(char, &str)> {
    let mut chars = x.chars();
    let first = chars.next()?;
    Some((first, chars.as_str()))
}

impl<V> Tree<V> {
    pub fn get_mut(&mut self, key: &str) -> Option<&mut V> {
        let mut current_node: &mut Tree<V> = self;
        let mut key_index: usize = 0;

        loop {
            match str_split_first(&key[key_index..]) {
                Some((c, _)) => {
                    let mut found: bool = false;

                    'child_loop: for (character, child) in current_node.children.iter_mut() {
                        if c == *character {
                            current_node = child;
                            found = true;
                            break 'child_loop;
                        }
                    }

                    // If nothing was found, this key does not exist.
                    if found == false {
                        return None;
                    }

                    key_index += 1;
                }
                _ => break,
            }
        }

        let val_opt: Option<&mut V> = current_node.val.as_mut();
        return match val_opt {
            Some(val) => return Some(val),
            None => None,
        };
    }
}
#[派生(调试、克隆、部分Q、均衡)]
pub结构树{
瓦尔:选项,
儿童:Vec,
}
fn str_split_first(x:&str)->选项{
设mut chars=x.chars();
设first=chars.next()?;
一些((首先,chars.as_str()))
}
impl树{
pub fn get_mut(&mut self,key:&str)->选项{
让mut current_node:&mut Tree=self;
让mut key_index:usize=0;
环路{
首先匹配str\u split\u(&key[key\u index..)){
一些((c,)))=>{
让mut找到:bool=false;
'child_loop:for(character,child)在当前_节点中。children.iter_mut(){
如果c==*字符{
当前_节点=子节点;
发现=真;
打破“儿童循环”;
}
}
//如果未找到任何内容,则此密钥不存在。
如果找到==false{
不返回任何值;
}
键索引+=1;
}
_=>休息,
}
}
让val_opt:Option=current_node.val.as_mut();
返回匹配值{
Some(val)=>返回Some(val),
无=>无,
};
}
}

这里的问题是,在迭代当前节点的子节点时,您正在修改当前节点。Rust编译器试图保护您免受迭代器失效的影响,但在本例中,这样做实际上是正确的,因为在更改
当前\u节点的值后,迭代立即停止

不幸的是,编译器还不够聪明,无法看到它。一个简单的解决方法是在某个临时变量中存储一个新值,并在循环外部更新
当前\u节点。像这样:

让mut found=None;
对于当前_node.children.iter_mut()中的(字符,子项){
如果c==*字符{
发现=一些(儿童);
打破
}
}
当前_节点=找到匹配项{
一些(孩子)=>孩子,
None=>返回None,
};

您能提供一份详细的报告吗?实际上,很难帮助您,因为没有足够的代码来重现错误。似乎您可能会从的答案中受益。@Aplet123我在OP的底部添加了完整的代码。旁注:您的
return
语句不必要地复杂。您可以
返回val\u opt而不是匹配它并重建一个相同的
选项
。这是正确的,尽管使用比在中断时执行变量循环更惯用,@darksv Great我会尝试一下@kmdreko我也会尝试一下
find()
——我对这门语言还是新手,所以我不知道更地道的功能。谢谢你提供的信息。@darksv非常感谢你。实施后,它就像一个符咒。现在看来很明显,更新我(某种程度上)迭代的变量会让编译器对我大喊大叫。谢谢你的帮助。@kmdreko是的。我认为使用
而让
作为外部循环会更加惯用:)
for child in current_node.children.iter_mut() {
  ...
}
let val_opt: Option<&mut V> = current_node.val.as_mut();
return match val_opt {
  Some(val) => {
    return Some(val)
  },
  None => None
}
cannot borrow `current_node.children` as mutable more than once at a time. mutable borrow starts here in previous iteration of loop.

let's call the lifetime of this reference `'1` (start of the function)

mutable borrow starts here in previous iteration of loop (child loop)

returning this value requires that `current_node.children` is borrowed for `'1` (on the line where I return Some(val) at the very end of the function)
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Tree<V> {
    val: Option<V>,
    children: Vec<(char, Tree<V>)>,
}

fn str_split_first(x: &str) -> Option<(char, &str)> {
    let mut chars = x.chars();
    let first = chars.next()?;
    Some((first, chars.as_str()))
}

impl<V> Tree<V> {
    pub fn get_mut(&mut self, key: &str) -> Option<&mut V> {
        let mut current_node: &mut Tree<V> = self;
        let mut key_index: usize = 0;

        loop {
            match str_split_first(&key[key_index..]) {
                Some((c, _)) => {
                    let mut found: bool = false;

                    'child_loop: for (character, child) in current_node.children.iter_mut() {
                        if c == *character {
                            current_node = child;
                            found = true;
                            break 'child_loop;
                        }
                    }

                    // If nothing was found, this key does not exist.
                    if found == false {
                        return None;
                    }

                    key_index += 1;
                }
                _ => break,
            }
        }

        let val_opt: Option<&mut V> = current_node.val.as_mut();
        return match val_opt {
            Some(val) => return Some(val),
            None => None,
        };
    }
}