1

In these two examples is there any benefit in using .iter() in a for loop?

let chars = ['g', 'd', 'k', 'k', 'n'];

for i in chars {
    println!("{}", i);
}

let chars = ['g', 'd', 'k', 'k', 'n'];

for i in chars.iter() {
    println!("{}", i);
}
Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
Kuly14
  • 496
  • 3
  • 12
  • Which language edition are you using? – SirDarius Sep 04 '22 at 17:32
  • The first version, without the explicit call to `.iter()`, implicitly calls `.into_iter()` from the `IntoIterator` trait. One consequence of this is that the loop will *take ownership* of `chars` instead of borrowing it; a second consequence is that `i` will be the owned `char` from the array instead of a reference to it. – eggyal Sep 04 '22 at 18:17
  • 1
    The language edition is important here because behaviour regarding array iteration changed between edition 2018 and 2021 (see https://doc.rust-lang.org/edition-guide/rust-2021/IntoIterator-for-arrays.html). – SirDarius Sep 04 '22 at 18:20

1 Answers1

2

for i in array is interpreted by the compiler as for i in array.into_iter().

This means that you are iterating over elements of type char, and the array is copied (as an array is Copy if its elements are also Copy).

On the other hand, for i in array.iter() references the array instead iterates over elements of type &char, avoiding a copy.

SirDarius
  • 41,440
  • 8
  • 86
  • 100
  • 2
    You can also do `for i in &array` in 2021 and it would be interpreted as `for i in (&array).into_iter()`, which is equivalent to `for i in array.iter()` . – Bamontan Sep 04 '22 at 19:29
  • Wrong. The edition doesn't matter. It only matters for explicit `.iter()`. If you'd be using an old version it would matter, but it will just not compile. – Chayim Friedman Sep 04 '22 at 23:56
  • Another thing to note is that because the array is `Copy`, this will not move it. – Chayim Friedman Sep 04 '22 at 23:58
  • @ChayimFriedman Amended the answer to take into account the `Copy` behaviour. I'm still not convinced that edition does not matter, given that if in edition 2021, the implicit `for in array` form calls into_iterator, and performs a copy, it's certainly different behaviour than just referencing the array. – SirDarius Sep 05 '22 at 09:34
  • @SirDarius That is the point, that in edition <= 2018 you _also_ copy the array and not reference it. – Chayim Friedman Sep 05 '22 at 10:47
  • @ChayimFriedman And this is the hacky part I reckon? I found the reference to this behaviour in the documentation. In 2018, if we use the short syntax, it translates to `array.into_iter()`, while explicitely writing `array.into_iter()` translates to `(&array).into_iter()`. Unfortunately, I can't delete my answer unless it is unaccepted. I'll amend instead. – SirDarius Sep 05 '22 at 12:26
  • The difference between editions is what happens when you use _explicit_ `.into_iter()`. This is pretty hacky, yes. The problem was the existing code relied on `array.into_iter()` to be the same as `array.iter()`, so this behavior was left unchanged. But existing code did not rely on for loop over `array` directly to be the same as `.iter()`, since it didn't compile (because the desugaring is not `array.into_iter()` but `IntoItrator::into_iter(array)`, and that does not account for auto deref). – Chayim Friedman Sep 05 '22 at 13:35