[英]Is it possible to implement a custom Iterator::sum in Rust?
I am trying to learn about iterators with an iterator that produces triangle numbers.我正在尝试使用生成三角形数的迭代器来了解迭代器。 Triangle numbers are 1, 3, 6, 10, 15 where 1 = 1, 3 = 1 + 2, 6 = 1 + 2 + 3 etc. I have the basics of this created:三角形数是 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)
}
}
A quick runnable example of this is一个快速运行的例子是
let t = Triangle { cur: 0, n: 0, m: 10 };
let s: u32 = t.sum();
println!("{}", s); // prints 220
Is it possible to create a custom summation function for the iterator that returns type u32
?是否可以为返回类型u32
的迭代器创建自定义求和函数? I was hoping to be able to do this with the default iterator and sum functions, and not have to make my own specialized function.我希望能够使用默认的迭代器和 sum 函数来做到这一点,而不必制作我自己的专用函数。
What I was hoping to be able to do is:我希望能够做的是:
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
}
}
but this does not work.但这不起作用。 The error that I get with this is我得到的错误是
error[E0404]: expected trait, found struct `Triangle`
--> src/main.rs:26:12
|
26 | I: Triangle,
| ^^^^^^^^ not a trait
I could change it from Triangle
to Iterator
like it wants, but that would prevent me from accessing the m
and n
values of the Triangle
struct.我可以根据需要将它从Triangle
更改为Iterator
,但这会阻止我访问Triangle
结构的m
和n
值。
How do I do this?我该怎么做呢? Is it impossible?不可能吗? I know that I could write my own function like my_sum()
, but I was hoping to be able to do it in the context of an iterator.我知道我可以编写自己的函数,比如my_sum()
,但我希望能够在迭代器的上下文中做到这一点。
You cannot specialize the existing implementation of Sum
, but you can specialize Iterator::sum
in your iterator!你不能特化现有的Sum
实现,但你可以特化Iterator::sum
在你的迭代器中! It's a bit tricky, though, since its return type is generic.不过,这有点棘手,因为它的返回类型是通用的。
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))
}
}
We cannot return a fixed type (such as u32
), as that would not respect the contract defined by the Iterator
trait.我们不能返回固定类型(例如u32
),因为这不符合Iterator
trait 定义的契约。 All we know about the return type S
is that it implements Sum<Self::Item>
.我们只知道返回类型S
实现了Sum<Self::Item>
。 Sum
has a single method, sum
, that returns Self
, so we can use it to produce a value of type S
. Sum
有一个返回Self
方法sum
,因此我们可以使用它来生成S
类型的值。 The method expects an iterator;该方法需要一个迭代器; we feed it a Once
, "an iterator that yields an element exactly once".我们给它一个Once
,“一个只产生一次元素的迭代器”。 Since that iterator will iterate a fixed number of times, we can expect sum
to perform a fixed number of operations.由于该迭代器将迭代固定次数,我们可以预期sum
执行固定次数的操作。
When you compile the program in release mode and S
is u32
, the whole sum
call is optimized away, and the function returns msum - nsum
directly.当你在发布模式下编译程序并且S
是u32
,整个sum
调用被优化掉,函数直接返回msum - nsum
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.