イテレータ

Iteratorトレイトは配列のようなコレクションにイテレータを実装するトレイトです。

このトレイトは次の要素を表すnextメソッドのみ実装すればよく、これはimplブロックで 実装するか、(配列やrangeのように)もう実装されていることもあります。

一般的なシチュエーションでの利便性のため、forは自動的にコレクションに対して .into_iter()メソッドを使い、イテレータを作ります。

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

// `Fibonacci`に`Iterator`を実装する。
// `Iterator`トレイトは、次の要素を返す`next`メソッドのみ実装されていれば良い。
impl Iterator for Fibonacci {
    type Item = u32;
    
    // ここで、`.curr`と`.next`を使って数列を作り、
    // `Option<T>`型を返します。
    //     * `Iterator`が終われば、`None`を返します。
    //     * そうでなければ、次の値を`Some`でくるみ、返却します。
    fn next(&mut self) -> Option<u32> {
        let new_next = self.curr + self.next;

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

        // フィボナッチ数列には終わりは無いため、`Iterator`は`None`を
        // 返さず、いつも`Some`を返します。
        Some(self.curr)
    }
}

// フィボナッチ数列生成器を返す。
fn fibonacci() -> Fibonacci {
    Fibonacci { curr: 0, next: 1 }
}

fn main() {
    // `0..3`は0、1、2からなるイテレータを生成する
    let mut sequence = 0..3;

    println!("Four consecutive `next` calls on 0..3");  // 0..3から4回連続で`next`を呼ぶ。
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());
    println!("> {:?}", sequence.next());

    // `for`はイテレータを`None`が出るまで続ける。
    // それぞれの`Some`は変数(ここでは`i`)に分割代入される。
    println!("Iterate through 0..3 using `for`");  // `for`を使って0..3に対して繰り返し処理をする。
    for i in 0..3 {
        println!("> {}", i);
    }

    // `take(n)`メソッドは最初`n`回分のイテレータを返す
    println!("The first four terms of the Fibonacci sequence are: ");  // フィボナッチ数列の最初の4つは:
    for i in fibonacci().take(4) {
        println!("> {}", i);
    }

    // `skip(n)`メソッドは最初の`n`回をなくしたイテレータを返す。
    println!("The next four terms of the Fibonacci sequence are: ");  // フィボナッチ数列の次の4つは:
    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);
    }
}