我对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
,但是我希望能够在迭代器的上下文中完成它。
答案 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
执行固定数量的操作。
当您在发布模式下编译程序且S
为u32
时,整个sum
调用将被优化掉,函数将直接返回msum - nsum
。