Iterator method is only available for boxed Iterator

example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=af06464bb7499c93196afeab8c990a33

I'm trying to make an accumulator method for iterators, similar to the Python implementation.

I can't quite figure out why it only wants to work on Iterators wrapped in Box, Arc..etc. If I wrap the calling iterator in one of those, it only works on the Box< Box < Iterator>> etc...

struct Accumulate<I>
where
    I: Iterator,
{
    accum: Option<I::Item>,
	underlying: I,
	acc_fn: Box<dyn FnMut(I::Item, I::Item) -> I::Item>,
}

impl<I> Iterator for Accumulate<I>
where
    I: Iterator,
    I::Item: Hash + Eq + Clone,
{
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        match self.underlying.next(){
			Some(x) => {
				let new_accum = match self.accum.clone(){
					Some(accum) => (self.acc_fn)(accum, x),
					None => x,
				};
				self.accum = Some(new_accum.clone());
				Some(new_accum)
			},
			None => None,
		}		
    }
}

trait Accumulator: Iterator {
    fn accumulate<F: 'static>(mut self, mut f: F) -> Accumulate<Self>
    where
		F: FnMut(Self::Item, Self::Item) -> Self::Item,
        Self::Item: Hash + Eq + Clone,
        Self: Sized,
		
    {
        Accumulate {
            accum: None,
			underlying: self,
			acc_fn: Box::new(f),
        }
    }
}

impl<I: Iterator> Accumulator for I {}

Error message:


error[E0599]: no method named `accumulate` found for struct `std::ops::Range<{integer}>` in the current scope
  --> src/lib.rs:56:33
   |
35 |     fn accumulate<F: 'static>(mut self, mut f: F) -> Accumulate<Self>
   |        ----------
   |        |
   |        the method is available for `std::boxed::Box<std::ops::Range<{integer}>>` here
   |        the method is available for `std::sync::Arc<std::ops::Range<{integer}>>` here
   |        the method is available for `std::rc::Rc<std::ops::Range<{integer}>>` here
...
56 |         let result: Vec<i32> = (1..5).accumulate(|x,y| x + y).collect();
   |                                       ^^^^^^^^^^ method not found in `std::ops::Range<{integer}>`
   |
   = help: items from traits can only be used if the trait is in scope
   = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
           `use crate::Accumulator;`

Last thing, should I really be using the 'static lifetime here? The compiler keeps recommending it but I'm not sure if I should.

Much thanks in advance :slight_smile:

I don’t know about those suggestions, the error message is confusing. The problem is that trait methods are only available when the trait is in scope. Add a use super::Accumulator into tests.

you mean for the function/closure, right? Try to seek some inspiration from existing iterator adaptors like Map and avoid boxing the closure.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.