Rust言語のfor構文と IntoIteratorトレイト に関するメモ。[本記事はRust 1.11/Stable準拠]
for x in expression { // ループ本体 }
Rust公式ドキュメントによれば、forループでは下記コードと等価な処理が行われる。式 expression に対して IntoIterator::into_iter
メソッドが適用される。
match IntoIterator::into_iter(expression) { mut iter => loop { match iter.next() { Some(x) => { // ループ本体 }, None => break, } } }
IntoIterator
トレイトは「Iterator
トレイトを実装する任意の型」に対しても実装されており、この場合IntoIterator::into_iter(expression)
は何もせず expression
をそのまま返す*1。コレクションのinto_iter
/iter
/iter_mut
メソッドはIteratorトレイトを実装する型*2を返すため、下記コードはそれぞれ期待通り動作する。
let v1 = vec![1, 2, 3]; for x in v1.into_iter() { /*...*/ } let v2 = vec![1, 2, 3]; for x in v2.iter() { /*...*/ } let mut v3 = vec![1, 2, 3]; for x in v3.iter_mut() { /*...*/ }
メモ:Rust標準ライブラリのVec
構造体は、IntoIterator
トレイトを実装するためinto_iter
メソッドを提供するが、iter
/iter_mut
メソッドは直接的に提供しない。Vec<T>
のDeref
トレイト実装によりスライス[T]
へと自動デリファレンスされ、スライス・プリミティブのiter
/iter_mut
メソッドが呼び出される。
関連URL
*1:https://github.com/rust-lang/rust/blob/1.11.0/src/libcore/iter/traits.rs#L252-L260
*2:各モジュールで提供される IntoIter / Iter / IterMut 構造体がそれぞれIteratorトレイトを実装する。構造体名は慣例的なものに過ぎないが、イテレータを値で返す関数といった特殊ケースを除けば、イテレータの具象型を直接記述する必要は生じない。