2

I'm having difficulty understanding why this snippet from The Rust Book, Chapter 10 works:

fn largest(arr: &[i32]) -> i32 {
    let mut max = arr[0];
    for &i in arr.iter() {
        if i > max {
            max = i;
        }
    }
    max
}

Assumption A: Using arr.iter() will return references to the items in the array/slice/vector when iterating over it. So i will be of type &i32. Adding the extra & in the definition will make it a reference to a reference, so &&i32.

Assumption B: The IndexMut trait (used in line 2) will return a mutable reference to the item at index, so in this case a &mut i32.

Both of these assumptions are wrong, given that both i and max are of type i32. Why?


Additionally, I understand that i32 implements the Copy-trait, but since I'm not moving ownership anywhere in this code (because everything is a reference) it shouldn't be used here, right?


Lastly, if I leave the .iter()-call out, it works aswell. I assume that the compiler infers from the &i-definition, that the iter() should be used (and not iter_mut() or into_iter()), correct?

Lukas Knuth
  • 25,449
  • 15
  • 83
  • 111

1 Answers1

2

In

for &i in arr.iter() {

you're not adding a &: this is pattern matching. You're matching &i to the results of the iteration, thus removing the &.

It's effectively just like doing

for i in arr.iter() {
    let i = *i;
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • Can you expand on Assumption B ? – Lukas Knuth Jul 10 '19 at 14:52
  • `max` is of type `i32`, not `&i32` – Denys Séguret Jul 10 '19 at 15:02
  • Yeah, but why? As mentioned, the IndexMut trait should be used which says it will return `&mut i32`. Why is it `i32`? – Lukas Knuth Jul 10 '19 at 15:03
  • IndexMut would be used if the indexing was left side of the assignment, not right side, or with max = &mut arr[0]. And it would also need the array to be mutable. The trait used here is Index – Denys Séguret Jul 10 '19 at 15:13
  • Thats interesting, i didn't realize the side of assignment was relevant! But wouldn't that mean that `arr[0]` returns a `&i32` (as the Index-trait defines)? – Lukas Knuth Jul 10 '19 at 16:31
  • Read [there](https://doc.rust-lang.org/beta/std/ops/trait.Index.html): *"container[index] is actually syntactic sugar for *container.index(index)"* (the important detail is the `*`). As for the IndexMut it's not precisely the side of the assignment which matters but whether the context of the expression needs to be mutable (when it's left side of an assignment it always is). If you were to declare `let max: &i32 = &mut arr[0]` then you'd asking for a mutable context. – Denys Séguret Jul 10 '19 at 16:36