イテレータの実装が容易になった
今までRustではIteratorトレイトを使うことで独自イテレータを実装していました。例えばstartとendというフィールドを持つMyRangeという構造体があるとします。この構造体にイテレータを実装する場合、以下のような方法で行っていました。
struct MyRange {start: i32, end: i32}
impl Iterator for MyRange {
type Item = i32;
fn next(&mut self) -> Option<i32> {
if self.start >= self.end {
return None;
}
let result = Some(self.start);
self.start += 1;
result
}
}
fn main() {
let mut myrange = MyRange {start: 0, end: 2};
println!("{:?}", myrange.next()); // Some(0)
println!("{:?}", myrange.next()); // Some(1)
println!("{:?}", myrange.next()); // None
}
しかし
from_fn
を使うことで、より柔軟かつ簡潔にイテレータを実装することができるようです。上記のコードを変更してみます。
use std::iter::from_fn;
#[derive(Debug)]
struct MyRange {start: i32, end: i32}
fn main() {
let mut myrange = MyRange {start: 0, end: 2};
let mut itr = from_fn(|| {
myrange.start += 1;
if myrange.start <= myrange.end {
Some(myrange.start)
} else {
None
}
});
println!("{:?}", itr.next()); // Some(0)
println!("{:?}", itr.next()); // Some(1)
println!("{:?}", itr.next()); // None
}
同様の結果を得ることができました。つまり、必要な時、必要な形で利用できるイテレータを生成できるというわけです。例えば、イテレートする際のステップ数を1ではなく、2にしたい場合もあるでしょう。その時も、その場でちょいちょいと数字を変更すればいいだけなので、非常に柔軟性のある処理を行うことが可能です。今後うまく使えるようになっていきたいと思います。