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

2023-12-06

我在实现一个递归函数时遇到问题,该函数通过操作索引到不可变列表的可变索引列表来生成二叉树。

这是代码:

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应该只持续到单个递归调用结束build_tree in the let left_subtree陈述。然而,Rust 声称这种借用实际上会持续到整个周期结束。build_tree功能。

谁能解释一下:

  1. 为什么第一次借用会持续到最后build_tree函数,以及
  2. 像这样的函数如何在 Rust 中正确实现?

顺便说一句:如果我删除“let left_subtree =”和“let right_subtree =”(即,使用递归调用build_tree只是因为它们的副作用indices并通过NoneNode构造函数),代码编译得很好并且不会抱怨多次借用。为什么是这样?


的结果build_tree is Box<Tree<'r, T>>。借用一直延伸到函数末尾,因为结果仍然从切片借用,正如生命周期参数所证明的那样Tree.

EDIT:对于您的情况,以下更改是完全不必要的。只需删除'r来自indices范围:indices: &mut [uint]。否则,编译器会假设您仍然借用切片,因为返回的Tree将该寿命作为参数。通过消除生命周期indices,编译器将推断出不同的生命周期。


要将可变切片分成两部分,请使用split_at_mut. split_at_mut uses 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)
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Rust 中使用递归函数生成树结构时的多个可变借用 的相关文章

随机推荐