[SOLVED] Compile error when chaining .scan() into my own iterator adaptor

My code is below. The error message follows the code.

I found an example of how to write an iterator adaptor here. However, it does not seem to work with the Scan iterator. I would be grateful for any help. Thank you.

use std::iter::Iterator;

struct AddThreeIter<T> where T : Iterator<Item=i32>
{
    feed : T,
}

impl<T> AddThreeIter<T> where T : Iterator<Item=i32>
{
    fn new(feed: T) -> AddThreeIter<T>
    {
        AddThreeIter { feed }
    }
}

impl<T> Iterator for AddThreeIter<T> where T: Iterator<Item=i32>
{
    type Item = i32;
    fn next(&mut self) -> Option<Self::Item>
    {
        match self.feed.next() {
            None => { None },
            Some(x) =>
                {
                    Some(x+3)
                },
        }
    }
}

trait AddThree : Sized where Self : Iterator<Item=i32>
{
    fn addThree(self) -> AddThreeIter<Self>;
}

impl <I: Iterator<Item=i32>> AddThree for I
{
    fn addThree(self) -> AddThreeIter<Self>
    {
        AddThreeIter::new(self)
    }
}

fn main()
{
    let it = [1, 2, 3, 4].iter().cloned()
        .scan(0, |state, item| { *state += item; Some(state) })
        .addThree();
    for x in it.take(10)
    {
        println!("{}", x);
    }
}

> error[E0599]: no method named `addThree` found for type `std::iter::Scan<std::iter::Cloned<std::slice::Iter<'_, {integer}>>, {integer}, [closure@src/main.rs:44:18: 44:63]>` in the current scope
>   --> src/main.rs:44:65
>    |
> 44 |         .scan(1, |state, item| { *state += item; Some(state) }).addThree();
>    |                                                                 ^^^^^^^^ method not found in `std::iter::Scan<std::iter::Cloned<std::slice::Iter<'_, {integer}>>, {integer}, [closure@src/main.rs:44:18: 44:63]>`
>    |
>    = note: the method `addThree` exists but the following trait bounds were not satisfied:
>            `&mut std::iter::Scan<std::iter::Cloned<std::slice::Iter<'_, {integer}>>, {integer}, [closure@src/main.rs:44:18: 44:63]> : AddThree`
>            `&std::iter::Scan<std::iter::Cloned<std::slice::Iter<'_, {integer}>>, {integer}, [closure@src/main.rs:44:18: 44:63]> : AddThree`
>            `std::iter::Scan<std::iter::Cloned<std::slice::Iter<'_, {integer}>>, {integer}, [closure@src/main.rs:44:18: 44:63]> : AddThree`
>    = help: items from traits can only be used if the trait is implemented and in scope
>    = note: the following trait defines an item `addThree`, perhaps you need to implement it:
>            candidate #1: `AddThree`

state: &mut i32, not i32, so your adapter doesn't get applied because it only works for iterators over i32, not &mut i32

let it = [1, 2, 3, 4].iter().cloned()
        .scan(0, |state, item| { *state += item; Some(*state) }) // deref state before returning
        .addThree();

Thank you very much.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.