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

use*_*330 7 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

一个快速可运行的例子是

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

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

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

use std::iter::Sum;

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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

error[E0404]: expected trait, found struct `Triangle`
  --> src/main.rs:26:12
   |
26 |         I: Triangle,
   |            ^^^^^^^^ not a trait
Run Code Online (Sandbox Code Playgroud)

我可以将它Triangle改为Iterator想要它,但这会阻止我访问结构的值m和n值Triangle.如果有人能告诉我如何做到这一点,或者如果不可能,那就太棒了.我知道我可以编写自己的函数,就像其他东西一样my_sum(),但是我希望能够在迭代器的上下文中完成它.

Fra*_*gné 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))
    }
}
Run Code Online (Sandbox Code Playgroud)

我们无法返回固定类型(例如u32),因为它不遵守Iterator特征所定义的合同。我们对返回类型S的唯一了解就是它实现了Sum<Self::Item>。Sum有一个sum返回的单一方法,Self因此我们可以使用它来产生type的值S。该方法需要一个迭代器;我们为它提供一个Once“仅产生一次元素的迭代器”。由于该迭代器将迭代固定次数,因此我们可以期望sum执行固定次数的操作。

当您在释放模式编译程序和S是u32,整个sum呼叫被优化掉,并在函数返回msum - nsum直接。