我很难将独立的merge_sort
函数转换为Vec<T>
的特征。似乎我遇到了合并排序算法工作方式的生命周期错误。
我已经尝试在函数和特征声明中指定生命周期,但它仍然给我一个类似的错误。
我对生命的研究包括......
这是代码
trait MergeSortable<T> {
fn merge_sort(&mut self);
fn _merge(&self, left: &mut Vec<T>, right: &mut Vec<T>) -> &mut Vec<T>;
}
impl<T: Ord + Clone + PartialEq> MergeSortable<T> for Vec<T> {
fn merge_sort(&mut self) {
if self.len() <= 1 {
return;
}
let mid = self.len() / 2;
let mut left = self[..mid].to_vec();
left.merge_sort();
let mut right = self[mid..].to_vec();
right.merge_sort();
self = self._merge(&mut left, &mut right);
}
fn _merge(&self, left: &mut Vec<T>, right: &mut Vec<T>) -> &mut Vec<T> {
if left.len() == 0 {
return right;
}
if right.len() == 0 {
return left;
}
if left[0] < right[0] {
let mut v: Vec<T> = Vec::new();
v.push(left[0].clone());
v.extend_from_slice(&self._merge(&mut left[1..].to_vec().clone(), &mut right.clone())[..]);
return &mut v;
}
let mut v: Vec<T> = Vec::new();
v.push(right[0].clone());
v.extend_from_slice(&self._merge(&mut left.clone(), &mut right[1..].to_vec().clone())[..]);
return &mut v;
}
}
错误:
error: lifetime of reference outlives lifetime of borrowed content... [E0312]
--> <anon>:27:20
|>
27 |> return left;
|> ^^^^
note: ...the reference is valid for the anonymous lifetime #1 defined on the block at 22:75...
--> <anon>:22:76
|>
22 |> fn _merge(&self, left: &mut Vec<T>, right: &mut Vec<T>) -> &mut Vec<T> {
|> ^
note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the block at 22:75
--> <anon>:22:76
|>
22 |> fn _merge(&self, left: &mut Vec<T>, right: &mut Vec<T>) -> &mut Vec<T> {
|> ^
error: lifetime of reference outlives lifetime of borrowed content... [E0312]
--> <anon>:24:20
|>
24 |> return right;
|> ^^^^^
note: ...the reference is valid for the anonymous lifetime #1 defined on the block at 22:75...
--> <anon>:22:76
|>
22 |> fn _merge(&self, left: &mut Vec<T>, right: &mut Vec<T>) -> &mut Vec<T> {
|> ^
note: ...but the borrowed content is only valid for the anonymous lifetime #3 defined on the block at 22:75
--> <anon>:22:76
|>
22 |> fn _merge(&self, left: &mut Vec<T>, right: &mut Vec<T>) -> &mut Vec<T> {
|> ^
help: consider using an explicit lifetime parameter as shown: fn _merge<'a, 'b>(&'a self, left: &'a mut Vec<T>, right: &'b mut Vec<T>)
-> &mut Vec<T>
--> <anon>:22:5
|>
22 |> fn _merge(&self, left: &mut Vec<T>, right: &mut Vec<T>) -> &mut Vec<T> {
|> ^
答案 0 :(得分:4)
_merge
实际上并不需要self
参数。我们将其删除:
use std::cmp::Ord;
use std::clone::Clone;
trait MergeSortable<T> {
fn merge_sort(&mut self);
fn _merge(left: &mut Vec<T>, right: &mut Vec<T>) -> &mut Vec<T>;
}
impl<T: Ord + Clone + PartialEq> MergeSortable<T> for Vec<T> {
fn merge_sort(&mut self) {
if self.len() <= 1 {
return;
}
let mid = self.len() / 2;
let mut left = self[..mid].to_vec();
left.merge_sort();
let mut right = self[mid..].to_vec();
right.merge_sort();
self = Self::_merge(&mut left, &mut right);
}
fn _merge(left: &mut Vec<T>, right: &mut Vec<T>) -> &mut Vec<T> {
if left.len() == 0 {
return {right};
}
if right.len() == 0 {
return {left};
}
if left[0] < right[0] {
let mut v: Vec<T> = Vec::new();
v.push(left[0].clone());
v.extend_from_slice(&Self::_merge(&mut left[1..].to_vec().clone(), &mut right.clone())[..]);
return &mut v;
}
let mut v: Vec<T> = Vec::new();
v.push(right[0].clone());
v.extend_from_slice(&Self::_merge(&mut left.clone(), &mut right[1..].to_vec().clone())[..]);
return &mut v;
}
}
现在我们得到了一个不同的错误:
error: missing lifetime specifier [--explain E0106]
--> <anon>:6:57
|>
6 |> fn _merge(left: &mut Vec<T>, right: &mut Vec<T>) -> &mut Vec<T>;
|> ^^^^^^^^^^^
help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `left` or `right`
error: missing lifetime specifier [--explain E0106]
--> <anon>:22:57
|>
22 |> fn _merge(left: &mut Vec<T>, right: &mut Vec<T>) -> &mut Vec<T> {
|> ^^^^^^^^^^^
help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `left` or `right`
这有助于我们理解第一个问题:当有self
参数并且返回值是引用时,编译器将推断返回引用的生命周期与{{1}相关联}。在这里根本不是这样的!通过删除self
参数,编译器面临两个作为引用的参数,并且当前的省略规则使得必须必须指定显式生存期。
所以,让我们这样做!
self
但现在,我们遇到了更多错误。让我们关注这个:
use std::cmp::Ord;
use std::clone::Clone;
trait MergeSortable<T> {
fn merge_sort(&mut self);
fn _merge<'a>(left: &'a mut Vec<T>, right: &'a mut Vec<T>) -> &'a mut Vec<T>;
}
impl<T: Ord + Clone + PartialEq> MergeSortable<T> for Vec<T> {
fn merge_sort(&mut self) {
if self.len() <= 1 {
return;
}
let mid = self.len() / 2;
let mut left = self[..mid].to_vec();
left.merge_sort();
let mut right = self[mid..].to_vec();
right.merge_sort();
self = Self::_merge(&mut left, &mut right);
}
fn _merge<'a>(left: &'a mut Vec<T>, right: &'a mut Vec<T>) -> &'a mut Vec<T> {
if left.len() == 0 {
return right;
}
if right.len() == 0 {
return left;
}
if left[0] < right[0] {
let mut v: Vec<T> = Vec::new();
v.push(left[0].clone());
v.extend_from_slice(&Self::_merge(&mut left[1..].to_vec().clone(), &mut right.clone())[..]);
return &mut v;
}
let mut v: Vec<T> = Vec::new();
v.push(right[0].clone());
v.extend_from_slice(&Self::_merge(&mut left.clone(), &mut right[1..].to_vec().clone())[..]);
return &mut v;
}
}
您尝试返回对本地变量的引用。你不能这样做:你必须返回值本身,就像你在原始函数中所做的那样。有关详细信息,请参阅Return local String as a slice (&str)。
也许您不知道的一个技巧是,您可以通过指定其引用(error: `v` does not live long enough
--> <anon>:33:25
|>
33 |> return &mut v;
|> ^
note: reference must be valid for the lifetime 'a as defined on the block at 22:81...
--> <anon>:22:82
|>
22 |> fn _merge<'a>(left: &'a mut Vec<T>, right: &'a mut Vec<T>) -> &'a mut Vec<T> {
)来替换引用后面的值。
*self = new_value
我还会考虑将use std::cmp::Ord;
use std::clone::Clone;
trait MergeSortable<T> {
fn merge_sort(&mut self);
fn _merge(left: Vec<T>, right: Vec<T>) -> Vec<T>;
}
impl<T: Ord + Clone + PartialEq> MergeSortable<T> for Vec<T> {
fn merge_sort(&mut self) {
if self.len() <= 1 {
return;
}
let mid = self.len() / 2;
let mut left = self[..mid].to_vec();
left.merge_sort();
let mut right = self[mid..].to_vec();
right.merge_sort();
*self = Self::_merge(left, right);
}
fn _merge(left: Vec<T>, right: Vec<T>) -> Vec<T> {
if left.len() == 0 {
return right;
}
if right.len() == 0 {
return left;
}
if left[0] < right[0] {
let mut v: Vec<T> = Vec::new();
v.push(left[0].clone());
v.extend_from_slice(&Self::_merge(left[1..].to_vec(), right)[..]);
return v;
}
let mut v: Vec<T> = Vec::new();
v.push(right[0].clone());
v.extend_from_slice(&Self::_merge(left, right[1..].to_vec())[..]);
return v;
}
}
移出特征并进入自由函数,这样您就不必编写_merge
来调用它。
答案 1 :(得分:2)
在将其转换为特质版本之前,我不知道这是如何工作的。问题在于_merge
:
fn _merge(&self, left: &mut Vec<T>, right: &mut Vec<T>) -> &mut Vec<T>;
该签名实际上是以下的简写:
fn _merge<'a>(&'a self, left: &mut Vec<T>, right: &mut Vec<T>) -> &'a mut Vec<T>;
这意味着,返回的值必须是self
的借用。在您的情况下,这完全不正确,因为您要么返回left
或right
,要么返回一个全新的向量(以及can't return a reference to a local variable)。修复它的最简单方法是返回Vec<T>
。或者,如果您想在退回.clone()
或left
时保存right
,则可以返回Cow<[T]>
(我认为它不值得)虽然)。
另外,我认为_merge
并不真正属于特质,你甚至不在那里使用self
。我只是把它变成了一个功能。