【问题标题】:How do you extend a trait like itertools does with collect_vec()?你如何像 itertools 那样用 collect_vec() 扩展一个特征?
【发布时间】:2021-03-18 02:24:24
【问题描述】:

我想在itertools中创建一个类似于collect_vec()函数的方法。

复制itertools代码创建一个小例子:

pub trait MyItertools: Iterator {
    fn collect_vec(self) -> Vec<Self::Item>
        where Self: Sized
    {
        self.collect()
    }
}

fn main() {
    let v = (0..5).collect_vec();
    println!("{:?}", v);
}

我相当天真地期望编译器会使用我的collect_vec 作为 MyItertools 在范围内。

itertools 必须使用其他魔法来编译它。

我们得到错误:

error[E0599]: no method named `collect_vec` found for struct `std::ops::Range<{integer}>` in the current scope
  --> src/main.rs:14:20
   |
14 |     let v = (0..5).collect_vec();
   |                    ^^^^^^^^^^^ method not found in `std::ops::Range<{integer}>`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
note: `MyItertools` defines an item `collect_vec`, perhaps you need to implement it
  --> src/main.rs:5:1
   |
5  | pub trait MyItertools: Iterator {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

这具有误导性,因为我们确实在 MyItertools 中实现了 collect_vec

一个可能的解决方案是impl MyItertools Iterator,但似乎没有办法为所有实现特征和类型的Iterator 执行此操作。

【问题讨论】:

  • 不,不是,因为您实际上还没有为std::ops::Range 实现MyItertools 特征(这就是(0..5) 的含义)。你已经声明了这个特征,但你实际上并没有为任何类型实现它(至少在你的 MCVE 中)。要在SomeType 上实现特征,您必须添加一个impl MyItertools for SomeType 块(并确保SomeType 也实现Iterator)。
  • 谢谢,EvilTalk。正如我在编辑中建议的那样,我使用的所有类型都可以这样做,但 Itertools 似乎没有这样做,因此很神奇。

标签: generics rust iterator traits scoping


【解决方案1】:

谜题中缺少的魔法部分是一个通用的一揽子实现,它为所有实现 Iterator 特征的类型实现了 MyItertools 特征。更新固定示例:

pub trait MyItertools: Iterator {
    fn collect_vec(self) -> Vec<Self::Item>
        where Self: Sized
    {
        self.collect()
    }
}

impl<T> MyItertools for T where T: Iterator {}

fn main() {
    let v = (0..5).collect_vec();
    println!("{:?}", v);
}

playground

【讨论】:

  • 啊哈!很好的答案,@pretzelhammer。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-18
  • 2015-06-03
  • 2019-05-11
  • 2013-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多