forループ文

TL;DR

for文で回すには、以下のトレイトのどれかを実装する必要がある。

  • Iterator
  • IntoIterator

配列はforループで回せない

配列は、どちらも実装していないため、forループ文で直接回せない。

let arr = [1,2,3,4,5];
// NG 
for i in arr {
    dbg!(i);
}
/* 
error[E0277]: `[{integer}; 5]` is not an iterator
  --> /Users/yossan/testcodes/rust/garbage/vec_loop.rs:10:14
   |
10 |     for i in arr {
   |              ^^^ borrow the array with `&` or call `.iter()` on it to iterate over it
   |
   = help: the trait `Iterator` is not implemented for `[{integer}; 5]`
   = note: arrays are not iterators, but slices like the following are: `&[1, 2, 3]`
   = note: required by `into_iter`
*/
  • for文ないでは、スライス型への型強制がされない
  • 配列上で、スライス型のメソッドを呼び出すと、スライス型に型強制する

配列の参照はforループで回せる

配列の参照型はIntoIterator<Item=&T>を実装している。

impl<'a, T> IntoIterator for &'a [T]
    type Item = &'a T
    type IntoIter = Iter<'a, T>
for i in &arr { }

Vecはforループで回せる

Vecは、Iterator実装型ではないが、IntoIterator実装型であるため、for文で回すことが出来る。

impl<T, A: Allocator> IntoIterator for Vec<T, A> {
    type Item = T;
    type IntoIter = IntoIter<T, A>;

    fn into_iter(self) -> IntoIter<T, A> {

for文で使うと内部でinto_iterメソッドが呼び出されるため、所有権を失う

let vec = vec![1,2,3,4,5];
for i in vec {
    println!("{}", i);
}
dbg!(vec);
/*
2   |     let vec = vec![1,2,3,4,5];
    |         --- move occurs because `vec` has type `Vec<i32>`, which does not implement the `Copy` trait
3   |     for i in vec {
    |              ---
    |              |
    |              `vec` moved due to this implicit call to `.into_iter()`
    |              help: consider borrowing to avoid moving into the for loop: `&vec`
*/

参照型の方も実装されているので、所有権を失いたくない場合は、参照型の方を使う。

impl<'a, T> IntoIterator for &'a Vec<T>
    type Item = &'a T
    type IntoIter = Iter<'a, T>
let vec = vec![1,2,3,4,5];
for i in &vec {
    dbg!(i);
}