Storing an Iterator in a struct


#1

I’m trying to store an iterator and use it later.

In the code below, ERepeatGen is an Iterator that generates the infinite repeat pattern for the continued fraction representation of ‘e’

I want ContFrac to store that iterator and apply it in the rational_representation* function.

I’m getting a compiler error on x in both rational_representation* functions (I tried to code it two different ways) that says something like “expecting i64, getting type T: Iterator:: Item” (sorry I can’t exactly reproduce the error from here, but it looks like it doesn’t know what the iterator should produce??).

I’ve looked through the itertools crate to see how they “store” iterators, but I’m stumped by what I’m seeing. Any help is appreciated!

extern crate num;

use num::rational::Rational64;
use num::integer::Integer;
//...
struct ERepeatGen {
    current: u64,
}

impl ERepeatGen {
    fn new() -> ERepeatGen {
        ERepeatGen { current: 3 }
    }
}

impl Iterator for ERepeatGen {
    type Item = u64;
    fn next(&mut self) -> Option {
        let retval = if self.current % 3 == 1 {2 * (self.current / 3)} else {1};
        self.current += 1;
        Some(retval)
    }
}

struct ContFrac {
    start: u32,
    repeat: T,
}

impl ContFrac {
    fn new(s: u32, rep: T) -> ContFrac {
        ContFrac { start: s, repeat: rep }
    }

   fn rational_representation_1(&self, n: usize) -> Rational64 {
        let br_one = Rational64::new(1, 1);
        let mut retval = self.repeat.take(n).fold(Rational64::new(0, 1), |s, x| s + br_one / Rational64::from_integer(x));
        retval = self.start + br_one / retval;
   }

   fn rational_representation_2(&self, n: usize) -> Rational64 {
        let br_one = Rational64::new(1, 1);
        let mut remaining = n;
        let mut retval = Rational64::new(0, 1);
        while let Some(x) = self.repeat.next() {
            retval = retval + br_one / Rational64::from_integer(x);
            remaining -= 1;
            if remaining == 0 {break}
        }
        self.start + br_one / retval
   }
}

fn main() {
    let cf = ContFrac::new(2, ERepeatGen::new());
    let r = cf.rational_representation(99); //...

#2

impl<T: Iterator> ContFrac<T> means “For every type which is an iterator, a ContFrac of that type has these methods.” You’ve told the compiler that those methods have to be valid for any T: Iterator, so it can’t assume the iterator yields a certain type.

What you need is to bound this impl so that it is only valid for iterators of u64. The syntax for this is T: Iterator<Item=u64>.


#3

Thanks withoutboats! That did the trick.