首页 文章

在Rust中生成具有递归函数的树结构时,多个可变借用

提问于
浏览
2

我在实现一个递归函数时遇到了麻烦,该函数通过操纵索引到不可变列表的可变索引列表来生成二叉树 .

这是代码:

enum Tree<'r, T:'r> {                                                                                                                                                                                     
    Node(Box<Tree<'r, T>>,                                                                                                                                                                                
         &'r T,                                                                                                                                                                                           
         Box<Tree<'r, T>>),                                                                                                                                                                               
    Empty                                                                                                                                                                                                 
}                                                                                                                                                                                                         

fn process_elements<T>(xs: &mut [T]) {
    // interesting things happen here                                                                                                                                                                     
}

// This function creates a tree of references to elements in a list 'xs' by                                                                                                                               
// generating a permutation 'indices' of a list of indices into 'xs',                                                                                                                                  
// creating a tree node out of the center element, then recursively building                                                                                                                              
// the new node's left and right subtrees out of the elements to the left and                                                                                                                             
// right of the center element.                                                                                                                                                                           
fn build_tree<'r, T>(xs: &'r [T],
                     indices: &'r mut [uint]) -> Box<Tree<'r, T>> {
    let n = xs.len();
    if n == 0 { return box Empty; }
    process_elements(indices);
    let pivot_index = n / 2;
    let left_subtree =
        // BORROW 1 ~~~v
        build_tree(xs, indices.slice_to_or_fail_mut(&pivot_index));
    let right_subtree =
        // BORROW 2 ~~~v
        build_tree(xs, indices.slice_from_or_fail_mut(&(pivot_index + 1)));
    box Node(left_subtree, &xs[pivot_index], right_subtree)
}

当我尝试编译它时,我得到一个错误,说我不能一次多次使用 *indices 可变,其中第一次借用发生在标记为 BORROW 1 的注释中,第二次借用发生在 BORROW 2 处 .

我清楚地看到 *points 确实在这两个位置都被借用了,但在我看来, *points 的第一次借用应该只持续到 let left_subtree 语句中对 build_tree 的单个递归调用的结束 . 但是,Rust声称这种借用实际上持续到整个 build_tree 函数结束 .

谁能解释一下:

  • 为什么第一次借用持续到 build_tree 函数结束,并且

  • 如何在Rust中正确实现这样的函数?

顺便说一句:如果我删除"let left_subtree ="和"let right_subtree ="(即,仅对 indices 的副作用使用 build_tree 的递归调用并将 None 传递给 Node 构造函数),代码编译得很好并且不会抱怨多次借用 . 为什么是这样?

1 回答

  • 1

    build_tree 的结果是 Box<Tree<'r, T>> . 借用延伸到函数结束,因为结果仍然从切片借用,如 Tree 的寿命参数所证明 .

    EDIT :在您的情况下,完全没有必要进行以下更改 . 只需从 indices 参数中删除 'rindices: &mut [uint] . 否则,编译器假定您仍然从切片借用,因为返回的 Tree 将该生存期作为参数 . 通过删除 indices 上的生命周期,编译器将推断出不同的生命周期 .


    要将可变切片拆分为两个,请使用split_at_mut . split_at_mut 使用 unsafe 代码来解决编译器限制,但方法本身不是 unsafe .

    fn build_tree<'r, T>(xs: &'r [T],
                         indices: &'r mut [uint]) -> Box<Tree<'r, T>> {
        let n = xs.len();
        if n == 0 { return box Empty; }
        process_elements(indices);
        let pivot_index = n / 2;
        let (indices_left, indices_right) = indices.split_at_mut(pivot_index);
        let (_, indices_right) = indices_right.split_at_mut(1);
        let left_subtree = build_tree(xs, indices_left);
        let right_subtree = build_tree(xs, indices_right);
        box Node(left_subtree, &xs[pivot_index], right_subtree)
    }
    

相关问题