首页 文章

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

提问于
浏览
7

我是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 ,但这会阻止我访问 Triangle 结构的 mn 值 . 如果有人能告诉我如何做到这一点,或者如果不可能,那就太棒了 . 我知道我可以编写自己的函数,称为 my_sum() ,但我希望能够在迭代器的上下文中完成 .

1 回答

  • 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 trait定义的 Contract . 我们所知道的返回类型 S 就是它实现了 Sum<Self::Item> . Sum有一个返回 Self 的方法sum,因此我们可以使用它生成 S 类型的值 . 该方法需要一个迭代器;我们喂它Once,"an iterator that yields an element exactly once" . 由于迭代器将迭代固定次数,因此我们可以期望 sum 执行固定数量的操作 .

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

相关问题