イテレータ

Iteratorトレイトは、例えば配列のような、要素の集合に対してイテレータを実装するためのトレイトです。

このトレイトはnextの要素に相当するものを決定するためのメソッドのみを要求します。このメソッドはimplブロック内で手動で実装するか、あるいは(配列やrangeのように)自動で定義されます。

サッとイテレータを使いたい時は、for文で集合からイテレータを作成することが良くあります。これは.into_iter()メソッドを呼び出しています。

struct Fibonacci {
    curr: u32,
    next: u32,
}

// `Iterator`を`Fibonacci`に対して実装します。
// `Iterator`トレイトは次の要素を取得するメソッドの定義だけを要求します。
impl Iterator for Fibonacci {
    // We can refer to this type using Self::Item
    type Item = u32;

    // ここではイテレーションの流れを`.curr`と`.next`を使用して定義しています。
    // 返り値の型は`Option<T>`で、これは:
    //     * `Iterator`が終了した時は`None`を返します。
    //     * そうでなければ`Some`でラップされた値を返します。
    fn next(&mut self) -> Option<Self::Item> {
        let current = self.curr;

        self.curr = self.next;
        self.next = current + self.next;

        // フィボナッチ数列には終端がないので、`Iterator`は決して
        // `None`を返さず、常に`Some`が返されます。
        Some(current)
    }
}

// フィボナッチ数列のジェネレータを返します。
fn fibonacci() -> Fibonacci {
    Fibonacci { curr: 0, next: 1 }
}

fn main() {
    // `0..3`は0, 1, 2をジェネレートする`Iterator`。
    let mut sequence = 0..3;

    println!("Four consecutive `next` calls on 0..3");
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());

    // `for`は`None`を返すまで、イテレータを舐めていき、出てきた`Some`を
    // アンラップして変数(ここでは`i`)に束縛します。
    println!("Iterate through 0..3 using `for`");
    for i in 0..3 {
        println!("> {}", i);
    }

    // `take(n)`メソッドは`Iterator`を先頭から`n`番目の要素までに減らします。
    println!("The first four terms of the Fibonacci sequence are: ");
    for i in fibonacci().take(4) {
        println!("> {}", i);
    }

    // `skip(n)`メソッドは`Iterator`の先頭から`n`番目までの要素をとばします。
    println!("The next four terms of the Fibonacci sequence are: ");
    for i in fibonacci().skip(4).take(4) {
        println!("> {}", i);
    }

    let array = [1u32, 3, 3, 7];

    // `iter`メソッドは配列やスライスからイテレータを作成します。
    println!("Iterate the following array {:?}", &array);
    for i in array.iter() {
        println!("> {}", i);
    }
}