2016-05-02 4 views
0

私は定数(呼び出し時に)引数xのシーケンスx^2、x^2 + x、x^2 + 2x、x^2 + 3x ...を生成するIteratorを実装しようとしています。錆。どのように後継者が用語のインデックスに依存するIteratorを実装していますか?

私が理解しているように、実装のどの時点でも作業しなければならないのは、self.currself.nextです。シーケンスは、シーケンス内のアイテムのインデックスに依存するようです。

struct SquareMultiple { 
    // generates the sequence j = i^2, i^2+i, i^2+2i, i^2+3i, ..., 
    curr: i64, 
    next: i64, 
} 

// Implement `Iterator` for `SquareMultiple`. 
// The `Iterator` trait only requires a method to be defined for the `next` 
// element. 
impl Iterator for SquareMultiple { 
    type Item = i64; 

    // Here, we define the sequence using `.curr` and `.next`. 
    // The return type is `Option<T>`: 
    //  * When the `Iterator` is finished, `None` is returned. 
    //  * Otherwise, the next value is wrapped in `Some` and returned. 
    fn next(&mut self) -> Option<I64> { 

     // FIXME: What to do here? 
     let new_next = self.curr + self.next; 

     self.curr = self.next; 
     self.next = new_next; 

     // Since there's no endpoint to a SquareMultiple sequence, the 
     // `Iterator` will never return `None`, and `Some` is always returned. 
     Some(self.curr) 
    } 
} 

// Returns a SquareMultiple sequence generator 
fn squareseq() -> SquareMultiple { 
    SquareMultiple { curr: 1, next: 2 } 
} 

私もindex属性を持つ構造体に過負荷をかけると考えられ、それがこのパターンの乱用のように何とかようです。

これについてはどのような方法がありますか?

+1

を/iter/trait.Iterator.html#method.nth)メソッドを使用します。 – malbarbo

答えて

2

Iteratorを実装する構造体に任意の値を格納できます。現在の値と値をインクリメントするのが最も簡単です。

struct SquareMultiple { 
    curr: i64, 
    inc: i64, 
} 

impl Iterator for SquareMultiple { 
    type Item = i64; 

    fn next(&mut self) -> Option<i64> { 
     let val = self.curr; 
     self.curr += self.inc; 
     Some(val) 
    } 
} 

impl SquareMultiple { 
    fn new(x: i64) -> Self { 
     SquareMultiple { curr: x * x, inc: x } 
    } 
} 

fn main() { 
    for i in SquareMultiple::new(5).take(10) { 
     println!("{}", i); 
    } 
} 

イテレータが永遠に続くことを証明する価値があり、2^63を超えるとパニックまたはラップアラウンドします。

私はこのソリューションが好きです。なぜなら、これは全く増殖しないからです。何らかの理由で、私の脳は、増やすことは乗算よりも簡単だと考えています。あなたが本当にインデックスを使用する必要がある場合は、使用


RangeFrommapそれ:

fn main() { 
    let x = 5; 
    let clever = (0..).map(|i| x * (x + i)); 
    for i in clever.take(10) { 
     println!("{}", i); 
    } 
} 

あなたが別の関数が必要な場合、あなたはタイプを記述することができないとして、イテレータをボックスする必要があります。閉鎖:

fn square_multiple(x: i64) -> Box<Iterator<Item = i64>> { 
    Box::new((0..).map(move |i| x * (x + i))) 
} 

fn main() { 
    for i in square_multiple(5).take(10) { 
     println!("{}", i); 
    } 
} 

あなたが別の関数を必要とし最大のパフォーマンス場合(適切なサウンドを追加効果)は、新しいタイプを作成することができます代わりに `Index`形質の、あなたはhttps://doc.rust-lang.org/stable/std([`イテレータ:: nth`]実装する必要があります

use std::ops::RangeFrom; 

struct SquareMultiple { 
    iter: RangeFrom<i64>, 
    x: i64, 
} 

impl SquareMultiple { 
    fn new(x: i64) -> Self { 
     SquareMultiple { 
      iter: (0..), 
      x: x, 
     } 
    } 
} 

impl Iterator for SquareMultiple { 
    type Item = i64; 

    fn next(&mut self) -> Option<i64> { 
     self.iter.next().map(|i| self.x * (self.x + i)) 
    } 
} 

fn main() { 
    for i in SquareMultiple::new(5).take(10) { 
     println!("{}", i); 
    } 
} 
関連する問題