rust で正の奇数を小さい方から返すイテレーターを作ります。
iterator トレイトの定義は以下の通りです。
trait Iterator { type Item; fn next(&mut self) -> Option<Self::Item>; }
https://doc.rust-lang.org/std/iter/trait.Iterator.html
ドキュメンテーションでは、Required Methods を実装すればよいことがわかります。
fn main() { for x in Odd::new().take(10) { println!("{}", x); } } struct Odd { current: usize, } impl Odd { fn new() -> Odd { Odd { current: 1, } } } impl Iterator for Odd { type Item = usize; fn next(&mut self) -> Option<Self::Item> { self.current += 2; Some(self.current - 2) } }
1 3 5 7 9 11 13 15 17 19
take()は以下のように Iterator トレイトに実装されたメソッドであり、Iterator trait をジェネリクスに指定した構造体を利用していることが分かります。
take()が返す構造体は自動的にnext()を実装するので、先頭から指定した要素だけを抜き出した Iterator として動作することが分かります。
fn take(self, n: usize) -> Take<Self> pub struct Take<I> { iter: I, n: usize } impl<I> Iterator for Take<I> where I: Iterator{ type Item = <I as Iterator>::Item; #[inline] fn next(&mut self) -> Option<<I as Iterator>::Item> { if self.n != 0 { self.n -= 1; self.iter.next() } else { None } } ... }
IntoIterator
IntoIterator という trait もあります。
pub trait IntoIterator where <Self::IntoIter as Iterator>::Item == Self::Item, { type Item; type IntoIter: Iterator; fn into_iter(self) -> Self::IntoIter; }
Iterator は何もないところから要素の順序列を作り出すような型に対して使うものでしたが、
IntoIterator はすでに何らかの要素の順序列を内部に持つような型に対してそれを自然な順序で取り出せるような型に対して使うもののようです。
(理解が間違っていたら、優しくご指摘ください。)
例えば、vecや要素が32個までの配列などは、IntoIterator が実装されています。
これによって、for ループを呼び出した時に IntoIterator によって、Iteratorが取得されて、ループが意図通り動くという構造になっているようです。