简体   繁体   English

为迭代器实现另一个特征

[英]Implementing another Trait for Iterator

I'm trying to add another trait to all Iterator s.我正在尝试向所有Iterator添加另一个特征。 But I don't understand why it doesn't compile.但我不明白为什么它不能编译。

Here is the code:这是代码:

use std::fmt::Display;
use std::iter::Sum;

trait Topla<T> {
    fn topla(&mut self)-> T;
}

impl<T, I> Topla<T> for I
where
    T: Sum + Display,
    I: Iterator<Item = T>,
{
    fn topla(&mut self) -> T {
        self.sum()
    }
}

fn main() {
    let data = vec![1,2,3,5,8];
    println!("{:?}", data.iter().topla());
}

The problem reveals itself if we use fully-qualified trait syntax:如果我们使用完全限定的 trait 语法,问题就会显现出来:

fn main() {
    let data = vec![1,2,3,5,8u32];
    let mut iter = data.iter();
    println!("{:?}", Topla::<u32>::topla(&mut iter));
}
error[E0271]: type mismatch resolving `<std::slice::Iter<'_, u32> as std::iter::Iterator>::Item == u32`
  --> src/main.rs:22:22
   |
5  |     fn topla(&mut self) -> T;
   |     ------------------------- required by `Topla::topla`
...
22 |     println!("{:?}", Topla::<u32>::topla(&mut iter));
   |                      ^^^^^^^^^^^^^^^^^^^ expected reference, found `u32`
   |
   = note: expected reference `&u32`
                   found type `u32`
   = note: required because of the requirements on the impl of `Topla<u32>` for `std::slice::Iter<'_, u32>`

Changing Topla<u32> to Topla<&u32> gets us closer:Topla<u32>更改为Topla<&u32>让我们更接近:

Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `&u32: std::iter::Sum` is not satisfied
  --> src/main.rs:22:22
   |
5  |     fn topla(&mut self) -> T;
   |     ------------------------- required by `Topla::topla`
...
22 |     println!("{:?}", Topla::<&u32>::topla(&mut iter));
   |                      ^^^^^^^^^^^^^^^^^^^^ the trait `std::iter::Sum` is not implemented for `&u32`
   |
   = help: the following implementations were found:
             <u32 as std::iter::Sum<&'a u32>>
             <u32 as std::iter::Sum>
   = note: required because of the requirements on the impl of `Topla<&u32>` for `std::slice::Iter<'_, u32>`

The problem is that Sum<&u32> isn't implemented for &u32 ;问题是Sum<&u32>没有为&u32实现; it's implemented for u32 .它是为u32实现的。 Since we need to return a u32 and not &u32 , we need to loosen our requirements on T , from being the iterator type itself to just being Sum able with T.由于我们需要返回u32而不是&u32 ,因此我们需要放宽对T的要求,从作为迭代器类型本身到仅对 T 进行Sum

trait Topla<T> {
    fn topla(&mut self) -> T;
}

impl<T, I> Topla<T> for I
where
    T: Display + Sum<<I as Iterator>::Item>,
    I: Iterator,
{
    fn topla(&mut self) -> T {
        self.sum()
    }
}

fn main() {
    let data = vec![1,2,3,5,8u32];
    let mut iter = data.iter();
    println!("{:?}", Topla::<u32>::topla(&mut iter));
}

But now if we return to the original syntax, we get type inference failures that make our new API very annoying to use.但是现在如果我们回到原来的语法,我们会遇到类型推断失败,这使得我们的新 API 使用起来非常烦人。 We can get around this by being a little more strict with the API.我们可以通过对 API 更加严格来解决这个问题。

If we make Topla a subtrait of Iterator , we can reference the item type in the definition of the topla method, and therefore move the type parameter for the output into the method rather than the trait.如果我们让Topla成为Iterator的子特征,我们可以在topla方法的定义中引用项目类型,因此将 output 的类型参数移动到方法而不是特征中。 This will let us use the turbofish syntax like we do with sum() .这将让我们像使用sum()一样使用 turbofish 语法。 Finally we have:最后我们有:

use std::fmt::Display;
use std::iter::Sum;

trait Topla: Iterator {
    fn topla<T>(self) -> T
    where
        Self: Sized,
        T: Sum<<Self as Iterator>::Item>;
}

impl<I> Topla for I
where
    I: Iterator,
    <I as Iterator>::Item: Display,
{
    fn topla<T>(self) -> T
    where
        Self: Sized,
        T: Sum<<Self as Iterator>::Item>,
    {
        self.sum()
    }
}

fn main() {
    let data = vec![1, 2, 3, 5, 8];
    println!("{:?}", data.iter().topla::<u32>());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM