Tree 实现可变树结构

Tree 实现可变树结构,tree,rust,mutable,Tree,Rust,Mutable,我正在尝试动态构建一棵树,并在下降、叶子和备份期间修改树的部分内容。我相信我对如何在Rust做这样的事情有一个基本的误解。这是我的密码: struct Node { children: Vec<Node>, data: usize, } impl Node { pub fn new() -> Node { Node { children: vec![], data: 0,

我正在尝试动态构建一棵树,并在下降、叶子和备份期间修改树的部分内容。我相信我对如何在Rust做这样的事情有一个基本的误解。这是我的密码:

struct Node {
    children: Vec<Node>,
    data: usize,
}

impl Node {
    pub fn new() -> Node {
        Node {
            children: vec![],
            data: 0,
        }
    }

    pub fn expand(&mut self) {
        self.children = vec![Node::new(), Node::new()];
    }

    pub fn is_leaf(&self) -> bool {
        self.children.len() == 0
    }
}

pub fn main() {
    let mut root = Node::new();
    for _ in 0..10 {
        let mut node = &mut root;
        let mut path = vec![];
        // Descend and potential modify the node in the process
        while !node.is_leaf() {
            let index = 0;
            path.push(index);
            node = &mut node.children[index];
        }
        // Do something to the leaf node
        node.expand();
        // Do something during "backup" (in my case it doesn't matter
        // in which order the modification is happening).
        node = &mut root;
        for &i in path.iter() {
            node.data += 1;
            node = &mut node.children[i];
        }
    }
}

这里同时发生了一些事情。简单的答案是:您正试图为同一个项目创建多个可变借用。Rust禁止您创建多个借用,即使您没有尝试修改它们(因为这比试图正式证明您的程序是正确的要容易)

由于您基本上试图以命令式的方式实现递归函数,因此我建议您采用更具功能性的方法来解决问题。我将循环中的逻辑移到了递归函数中,该函数直接在
节点上实现

struct Node {
    children: Vec<Node>,
    data: usize,
}

impl Node {

    pub fn new() -> Node {
        Node {
            children: vec!(),
            data: 0
        }
    }

    pub fn expand(&mut self) {
        self.children = vec!(Node::new(), Node::new());
    }

    pub fn is_leaf(&self) -> bool {
        self.children.len() == 0
    }

    fn expand_leaf_and_inc(&mut self) {
        if self.is_leaf() {
            self.expand();
        } else {
            let index = 0;
            self.children[index].expand_leaf_and_inc();
        }
        self.data += 1
    }
}

pub fn main() {
    let mut root = Node::new();
    for _ in 0..10 {
        root.expand_leaf_and_inc();
    }
}

在上一个版本中,这是一个非常巧妙的技巧,在
path
的赋值过程中,您引入了一个新的作用域。我知道这一点!我想得太迫切了。我仍然需要接受锈的某种功能性质。
let mut root = Node::new();
for _ in 0..10 {
    let mut path = vec![];
    {
        let mut node = &mut root;
        // Descend and potential modify the node in the process
        while !node.is_leaf() {
            let index = 0;
            path.push(index);
            node = &mut {node}.children[index];
        }
        // Do something to the leaf node
        node.expand();
    }
    // Do something during "backup" (in my case it doesn't matter
    // in which order the modification is happening).
    let mut node = &mut root;
    for &i in path.iter() {
        node.data += 1;
        node = &mut {node}.children[i];
    }
}