Rust中的以下代码可以正常编译:
pub fn insertion_sort(data : &mut [int]){
let n = data.len();
for j in range(1, n){
let key = data[j];
// we insert data[j] into the sorted sequence
//data[0...j-1]
let mut i = j -1;
while data[i] > key{
data[i + 1] = data[i];
if i == 0{
break;
}
i -= 1;
}
data[i] = key;
}
}
但此刻,我将介绍泛型,如下所示:
pub fn insertion_sort<T : Ord>(data : &mut [T]){
let n = data.len();
for j in range(1, n){
let key = data[j];
// we insert data[j] into the sorted sequence
//data[0...j-1]
let mut i = j -1;
while data[i] > key{
data[i + 1] = data[i];
if i == 0{
break;
}
i -= 1;
}
data[i] = key;
}
}
编译器报告以下问题:
从用于内置类型的非通用代码转换为通用代码时,我们需要特别注意吗?错误消息听起来很神秘。
[编辑]
根据以下弗拉基米尔(Vladimir)的建议,我尝试使用切片的交换功能想出一个适用于T:Ord的版本
pub fn insertion_sort<T : Ord>(data : &mut [T]){
let n = data.len();
for j in range(1, n){
// we insert data[j] into the sorted sequence
//data[0...j-1]
let mut i = j -1;
while data[i] > data[i+1]{
data.swap(i + 1, i);
if i == 0{
break;
}
i -= 1;
}
}
}
最佳答案
是的,您需要格外小心,因为在原始代码段中,您使用了int
,它可以隐式地复制(实现 Copy
特性),而在第二段代码中,您仅使用了带有Ord
绑定(bind)的通用参数。默认情况下,Rust中的值是移动的,而不是复制的,这确实对您可以使用的值带来了一些限制。如果您编写的是<T: Ord+Copy>
而不是<T: Ord>
,则可以观察到这一点-您的代码将重新开始编译。但是,这不是适当的通用解决方案,因为很多类型不是Copy
。
首先,您应该阅读the official Rust guide,它解释了所有权和借用权以及除其他以外的Rust核心概念,这些概念对于有效使用Rust必不可少。您看到的错误是这些概念的结果。基本上,如果您对某个数据结构具有引用,则不能将任何内容移出该结构。切片是对连续数据块的引用;因为您没有指定Copy
上绑定(bind)的T
,所以Rust无法从切片中复制值,并且它也无法移动这些值,因为禁止从引用后面移动。因此它发出一个错误。
这样的行为听起来是限制性的,有时是限制性的。用其他语言(大多数是C语言)非常自然地完成的许多事情不能直接在Rust中完成。作为返回,Rust提供了巨大的安全保证。但是,有时候您确实需要编写本身是安全的东西,但是这种安全性对于编译器而言并不明显。当您实现基本的数据结构和算法(例如排序)时,通常会发生这种情况。最终的工具当然是unsafe
块,但是在这种情况下,您将不需要它们。 Rust在 std::mem
模块中提供了几个非常有用的功能,尤其是 swap()
和 replace()
。但是,专门针对切片,直接在切片上有一种称为 swap()
的方法。它在给定索引处交换元素。如果以交换操作的形式重新定义插入排序,则将能够编写完全通用的代码,即使这些代码不可复制,它们也适用于所有Ord
类型。我强烈建议您尝试此操作,因为这将帮助您了解如何编写底层的Rust程序。
另一方面,如果您事先知道只能使用基本类型(例如int
),则可以安全地将Copy
绑定(bind)到T
上,并保持原样。或者,您可以使用更多通用的Clone
绑定(bind),但是从切片中提取值时,您将需要调用clone()
方法:
pub fn insertion_sort<T: Ord+Clone>(data: &mut [T]) {
let n = data.len();
for j in range(1, n) {
let key = data[j].clone();
// we insert data[j] into the sorted sequence
//data[0...j-1]
let mut i = j -1;
while data[i] > key {
data[i + 1] = data[i].clone();
if i == 0 {
break;
}
i -= 1;
}
data[i] = key;
}
}
关于generics - 在对模板进行模板化时,使用rust 报告不能脱离取消引用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26460738/