イテレータについて整理

for式を書くと所有権まわりのエラーが出てしまい、よくわからなかったので整理する。

into_iter()

let numbers = vec![1, 2, 3];
for number in numbers {
  // numberは要素そのもの
}
// numbersは再利用不可

公式ドキュメントにある通り、for式はコレクションに対してIntoIteratorトレイトのinto_iter()を呼びIteratorトレイトを実装するものを生成する。そして、それに対しnext()を呼ぶことで要素を取り出す。

fn into_iter(self) -> Self::IntoIter

定義によるとinto_iter()selfを受けるため、Copyトレイトが実装されていなければmoveが発生する。なので、for式のあとで再利用しようとしてエラーが発生してしまう。

iter(), iter_mut()

let numbers = vec![1, 2, 3];
for number = numbers.iter() {
  // numberは要素への参照
}
// numbersは再利用可

ここからの話はVec型を想定する。moveを発生させたくない場合、iter()iter_mut()を使う。

pub fn iter(&self) -> Iter<T>

into_iter()とは違い、&selfを受けるのでmoveは発生しない。Vec型の実装だと、std::slice::Iter型を返す。なので、for式はこのIter型のinto_iter()を呼ぶことになるが、実装を見るとselfを返しているだけ。Iter型はIteratorトレイトも実装しているということになる。

let numbers = vec![1];
let mut iterator = numbers.iter();
assert_eq!(iterator.next(), Some(&1));
assert_eq!(iterator.next(), None);

Iter型のnext()の実装を見てみたけど、現時点では理解できそうになかった。ただ、上のコードの通り、next()は要素の不変の参照を返す。一方で、iter_mut()ではこれが可変の参照になる。