访问盒装嵌套结构中的值

时间:2017-07-04 11:01:38

标签: enums rust avl-tree ownership

我是Rust的新手,想要实现一个AVL-Tree。

我使用以下枚举来表示我的树:

enum AvlTree<T> {
    Leaf,
    Node {
        left: Box<AvlTree<T>>,
        right: Box<AvlTree<T>>,
        value: T
    }
}

在实施其中一个余额功能时,我面临着所有权和借款方面的一些问题。

我正在尝试编写一个函数,它接受AvlTree<T>并返回另一个AvlTree<T>。我的第一次尝试是这样的:

fn balance_ll(tree: AvlTree<T>) -> AvlTree<T> {
    if let AvlTree::Node {left: t, right: u, value: v} = tree {
        if let AvlTree::Node {left: ref tl, right: ref ul, value: ref vl} = *t {
            AvlTree::Leaf // Return a new AvlTree here
        } else {
            tree
        }
    } else {
        tree
    }
}

即使使用这个最小的例子,编译器也会返回错误:

error[E0382]: use of partially moved value: `tree`             
  --> avl.rs:67:17             
   |                           
63 |         if let AvlTree::Node {left: t, right: u, value: v} = tree {                                                       
   |                                     - value moved here    
...                            
67 |                 tree      
   |                 ^^^^ value used here after move           
   |                           
   = note: move occurs because `(tree:AvlTree::Node).left` has type `std::boxed::Box<AvlTree<T>>`, which does not implement the `Copy` trait                  

我认为,我正确地理解了错误消息,因为AvlTree::Node解构将取消树示例的所有权。我怎样才能防止这种情况发生?我已经尝试了各种各样的事情并且(取消)引用tree - 变量只是为了面对更多的错误。

此外,我想在新结构中使用一些提取的值,例如utlvl。这可能吗?你可以提供一个最小的例子吗?执行该函数后,我不需要访问旧树。

1 个答案:

答案 0 :(得分:3)

  

我认为,我正确地理解了错误消息,因为MessageDigest md=MessageDigest.getInstance("SHA-256"); md.update(pass.getBytes()); byte byteData[]=md.digest(); StringBuffer sb=new StringBuffer(); for(int i=0;i<byteData.length;i++) sb.append(Integer.toString((byteData[i] & 0xFF) + 0x100, 16).substring(1)); BufferedWriter output=new BufferedWriter(new FileWriter("passwords.txt",true)); output.write(userTF.getText()+" "+sb.toString()+"\n"); output.close(); 解构将取消树示例的所有权。

是。如果您之后仍需要能够使用AvlTree::Node,则需要复制它:

tree

或使用快速释放其所有权的辅助功能 - 但我认为没有包装盒模式是可能的:

#[derive(Clone)]
enum AvlTree<T> {...}

fn balance_ll<T: Clone>(tree: AvlTree<T>) -> AvlTree<T> {
    let copy = tree.clone();

    if let AvlTree::Node { left: t, right: u, value: v } = tree {
        if let AvlTree::Node { left: ref tl, right: ref ul, value: ref vl } = *t {
            AvlTree::Leaf // Return a new AvlTree here
        } else {
            copy
        }
    } else {
        tree
    }
}

由于你可能想要使用结构化值,你可能更喜欢#![feature(box_patterns)] impl<T> AvlTree<T> { fn is_left_node(&self) -> bool { if let &AvlTree::Node { left: ref t, right: ref u, value: ref v } = self { if let &box AvlTree::Node { left: ref tl, right: ref ul, value: ref vl } = t { true } else { false } } else { false } } } fn balance_ll<T>(tree: AvlTree<T>) -> AvlTree<T> { if tree.is_left_node() { AvlTree::Leaf } else { tree } } 变体,但也许另一个会给你一些额外的想法。