我是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(),但是我希望能够在迭代器的上下文中完成它.
您不能专门化的现有实现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直接。