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トレイトを実装する。構造体名は慣例的なものに過ぎないが、イテレータを値で返す関数といった特殊ケースを除けば、イテレータの具象型を直接記述する必要は生じない。