Is it possible to implement a regular Iterator :: sum in Rust?

I'm relatively new to Rust, and I'm trying to learn about iterators. The specific problem I'm working on is an iterator that creates the numbers of triangles (the numbers of triangles are 1, 3, 6, 10, 15, where 1 = 1, 3 = 1 + 2, 6 = 1 + 2 + 3 and t .d.). I have the basics of this created, shown here:

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 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 summing function for an iterator that returns type u32 . I was hoping that I could do this using the default iterator and summarization functions, and should not perform my specialized function.

I learned this, and what I was hoping to do is

 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 it does not work. The error I get with this is

 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 

I could change it from Triangle to Iterator as he wants, but this will prevent me from accessing the m and n values โ€‹โ€‹of the Triangle structure. If someone could tell me how to do this, or if this is not possible, that would be great. I know that I could write my own function called something else, like my_sum() , but I was hoping to do this in the context of an iterator.

+6
source share
1 answer

You cannot specialize an existing Sum implementation, but you can specialize Iterator::sum in your iterator! This is a bit complicated 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 (for example, u32 ), since this will not correspond to the contract defined by the Iterator attribute. All we know about the returned type S is that it implements Sum<Self::Item> . Sum has a single method, Sum , which returns Self , so we can use it to create a value of type S The method expects an iterator; we root it Once , "an iterator that gives an element exactly once." Since this iterator will iterate a fixed number of times, we can expect Sum to perform a fixed number of operations.

When you compile the program in release mode, and S - u32 , the whole Sum call is optimized, and the function returns msum - nsum directly.

+4
source

Source: https://habr.com/ru/post/1013056/


All Articles