yohhoyの日記

技術的メモをしていきたい日記

forループとイテレータ

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