我无法通过操作索引到不可变列表的可变索引列表来实现生成二叉树的递归函数。
以下是代码:
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
的第一次借用应该只持续到{{}的单个递归调用结束1 {}在build_tree
语句中。但是,Rust声称这种借用实际上持续到整个let left_subtree
函数结束。
任何人都可以解释一下:
build_tree
函数结束,顺便说一句:如果我删除“let left_subtree =”和“let right_subtree =”(即,仅对build_tree
的副作用使用build_tree
的递归调用并传递{ {1}}到indices
构造函数),代码编译得很好,不会抱怨多次借用。这是为什么?
答案 0 :(得分:1)
build_tree
的结果是Box<Tree<'r, T>>
。借用延伸到函数结束,因为结果仍然从切片借用,如Tree
的生命周期参数所示。
编辑:在您的情况下,完全没有必要进行以下更改。只需从'r
参数中删除indices
:indices: &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)
}