是否可以在Rust中实现自定义Iterator :: sum?

时间:2016-12-10 18:04:47

标签: iterator rust

我对Rust比较陌生,我正在尝试学习迭代器。我正在研究的具体问题是产生三角形数字的迭代器(三角形数字为1,3,6,10,15,其中1 = 1,3 = 1 + 2,6 = 1 + 2 + 3等)。我已经创建了这个基础知识,如下所示:

pub struct Triangle {
    cur: u32,
    n: u32,
    m: u32,
}

impl Iterator for Triangle {
    type Item = u32;

    fn next(&mut self) -> Option<u32> {
        if self.n == self.m {
            return None;
        }
        self.n = self.n + 1;
        self.cur = self.cur + self.n;

        Some(self.cur)
    }
}

这是一个快速可运行的例子

let t = Triangle { cur: 0, n: 0, m: 10 };
let s: u32 = t.sum();
println!("{}", s);  // prints 220

是否可以为返回类型u32的迭代器创建自定义求和函数。我希望能够使用默认的迭代器和求和函数来完成这个,而不必创建我自己的专用函数。

我已经看过这个了,我希望能够做的是

impl Sum<u32> for u32 {
    fn sum<I>(iter: I) -> Self where I: Triangle {
        let nsum = (self.n * (self.n + 1) * (self.n + 2)) / 6;
        let msum = (self.m * (self.m + 1) * (self.m + 2)) / 6;
        msum - nsum
    }
}

但这不起作用。我得到的错误是

error[E0404]: `Triangle` is not a trait
  --> src/sequences.rs:61:41
   |
61 |     fn sum<I>(iter: I) -> Self where I: Triangle {
   |                                         ^^^^^^^^ not a trait

我可以将其从Triangle更改为Iterator,但这会阻止我访问m的{​​{1}}和n值结构。如果有人能告诉我如何做到这一点,或者如果不可能,那就太棒了。我知道我可以编写自己的函数,例如Triangle,但是我希望能够在迭代器的上下文中完成它。

1 个答案:

答案 0 :(得分:5)

您不能专注于Sum的现有实现,但您可以在迭代器中专门化Iterator::sum!但是,它有点棘手,因为它的返回类型是通用的。

use std::iter::{self, Sum};

impl Iterator for Triangle {
    // existing members are unchanged

    fn sum<S>(self) -> S where S: Sum<Self::Item> {
        let nsum = (self.n * (self.n + 1) * (self.n + 2)) / 6;
        let msum = (self.m * (self.m + 1) * (self.m + 2)) / 6;
        S::sum(iter::once(msum - nsum))
    }
}

我们不能返回固定类型(例如u32),因为它不会尊重Iterator特征定义的契约。我们所知道的返回类型S就是它实现了Sum<Self::Item>Sum有一个方法sum,它返回Self,因此我们可以使用它来生成S类型的值。该方法需要一个迭代器;我们给它一个Once,&#34;一个迭代器,它只产生一次元素&#34;。由于该迭代器将迭代固定次数,因此我们可以期望sum执行固定数量的操作。

当您在发布模式下编译程序且Su32时,整个sum调用将被优化掉,函数将直接返回msum - nsum