Types 在库中扩展固有类型是一种糟糕的形式吗?

Types 在库中扩展固有类型是一种糟糕的形式吗?,types,rust,traits,monkeypatching,Types,Rust,Traits,Monkeypatching,我有一个函数downsample_vec,它接受一个vec并根据它们的位置删除它的一些值。我在注释正确的特征时遇到了困难,我只需要克隆和索引,但无法使其工作,因此我决定使用self,看看是否能说服编译器做出正确的推断: impl Vec<IndexMut<usize>> { fn downsample<usize>(&mut self, factor: usize) { let len = self.len();

我有一个函数downsample_vec,它接受一个vec并根据它们的位置删除它的一些值。我在注释正确的特征时遇到了困难,我只需要克隆和索引,但无法使其工作,因此我决定使用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);
            }
        }
    }
}
这会使编译错误必须指定trait`std::ops::Index`中关联类型`Output`的值[E0191]

我不确定如何指定输出类型,也没有找到任何关于如何指定输出类型的参考资料,只是写了一些关于traits的博客。我的主要资源是


首先,在特定的库中本地使用这样的monkeypatch Vec是一种不好的形式,还是有一种正确的方法可以做到这一点?我编写的原始独立函数可以在中查看。

关于您的代码,有几点内容

首先,您不能为未在自己的板条箱中定义的类型编写impl块。您所能做的最好的事情就是定义一个新的特性,然后为外来类型实现该特性。这是一种常见的做法,通常称为extensiontrait,使用命名方案*Ext,例如。所以我们可以这样建造它:

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
    }
}
如果DownSampleText特征在范围内,则可以对任何Vec对象调用downsample

但是,您的操作代码仍然包含一些错误/存在一些问题:

你说它接受一个向量并返回一个值较少的向量副本,但是你给我们的代码改变了向量而不是创建一个副本!请注意,您的描述与代码不匹配。 不检查因子==0 您的for循环不起作用:当我们在遍历索引时删除元素时,会导致索引无效。无论何时删除一个元素,都不能在该迭代中增加索引。 还要注意,您的算法在²上运行,因为remove是一个线性时间算法。这可能不是你想要的。
关于你的代码有几点

首先,您不能为未在自己的板条箱中定义的类型编写impl块。您所能做的最好的事情就是定义一个新的特性,然后为外来类型实现该特性。这是一种常见的做法,通常称为extensiontrait,使用命名方案*Ext,例如。所以我们可以这样建造它:

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
    }
}
如果DownSampleText特征在范围内,则可以对任何Vec对象调用downsample

但是,您的操作代码仍然包含一些错误/存在一些问题:

你说它接受一个向量并返回一个值较少的向量副本,但是你给我们的代码改变了向量而不是创建一个副本!请注意,您的描述与代码不匹配。 不检查因子==0 您的for循环不起作用:当我们在遍历索引时删除元素时,会导致索引无效。无论何时删除一个元素,都不能在该迭代中增加索引。 还要注意,您的算法在²上运行,因为remove是一个线性时间算法。这可能不是你想要的。
感谢您指出函数描述问题。我已经做了太多的编辑和调整的问题,因为我弄乱了它。感谢您指出的功能描述问题。我对这个问题做了太多的编辑和调整,因为我把它弄得一团糟。