我有一个函数downsample_vec
,它接受Vec
并根据其位置删除一些值。我无法对正确的特征进行注释(我只需要Clone
和Index
,但无法使其正常工作),所以我决定使用self
来查看是否可以说服编译器做出正确的推论:
impl Vec<IndexMut<usize>> {
fn downsample<usize>(&mut self, factor: usize) {
let len = self.len();
if factor > len {
self.clear(); // downsample factor skips all elements
} else if factor == 1 {
return; // no actual downsampling
}
for ind in 0..len() {
if ind % factor != 0 {
self.remove(ind);
}
}
}
}
这给出了编译错误the value of the associated type `Output` (from the trait `std::ops::Index`) must be specified [E0191]
。
我不确定如何指定输出类型,并且没有找到关于如何执行此操作的任何参考,只是关于特征的博客。我的主要资源是the rust vec .retain()
source。
首先在特定的库中,这样的本地monkeypatch Vec
是不好的形式,还是有正确的方法来做到这一点? (我写的原始单独函数可以在the playground)中查看。
答案 0 :(得分:4)
您的代码有一些内容。
首先,您不能为您未在自己的箱子中定义的类型编写impl
- 块。您可以做的最好的事情是定义一个新的特征,然后为外来类型实现该特征。这是常见做法,通常称为“扩展特征”,使用命名方案*Ext
,例如MetadataExt
。所以我们可以像这样构建它:
trait DownsampleExt {
fn downsample(&mut self, factor: usize);
}
现在我们必须为Vec
实施它。在您的代码中,您使用IndexMut
特征,就好像您要确保向量本身是可变索引的一样。但由于Vec
已经是具体类型(或者更确切地说是类型构造函数),因此编译器已经知道它是可变索引的。所以这已经奏效了:
impl<T> DownsampleExt for Vec<T> {
fn downsample(&mut self, factor: usize) {
// action code
}
}
如果DownsampleExt
特征在范围内,您可以在任何downsample
对象上调用Vec
。
但是,您的操作代码仍然包含一些错误/存在一些问题:
factor == 0
for
循环不起作用:当我们在迭代索引时删除元素时,索引无效。每当删除一个元素时,都不能在该迭代中增加索引。 remove
是线性时间算法。这可能不是你想要的。