Beginner question: references and compairison

Hello - I am going through the Rust Programming Language book and have written a function to find the largest number in a vector. In doing this I have realized I do not understand how references work when iterating over a collection. I've gotten the function to work, but only after the compiler guided me in the right direction.

I wrote my function, which looked like this. This does not compile.

fn largest (list: &Vec<i32>) -> i32 {
    if list.len() == 0 {
        panic!("Attempted to find largest element of an empty list");
    }

    let mut largest = list[0];
    
    for num in list {
        if num > largest {
            largest = num;
        }
    }
    largest
}

For the function above, the compiler says:
expected `&i32`, found `i32` help: consider borrowing here: '&largest'

I understand that I am trying to compare a reference and a raw i32, and the compiler does not allow this because of the type mismatch.

The compiler guided me through a solution of creating a reference to largest and de-referencing num when assigning the value to largest, like so:

fn largest (list: &Vec<i32>) -> i32 {
    if list.len() == 0 {
        panic!("Attempted to find largest element of an empty list");
    }

    let mut largest = list[0];
    
    for num in list {
        if num > &largest {
            largest = *num;
        }
    }
    largest
}

However I also found (and this is what confuses me) that this solution will compile:

fn largest (list: &Vec<i32>) -> i32 {
    if list.len() == 0 {
        panic!("Attempted to find largest element of an empty list");
    }

    let mut largest = list[0];
    
    for &num in list {
        if num > largest {
            largest = num;
        }
    }
    largest
}

Here we are taking a reference to num and everything just works? I don't understand how I am not comparing &i32 (num) and i32 (largest) again? Why do I not get a compiler error here? Clearly I have a misunderstanding in what is going on here. Any help is greatly appreciated.

Thanks!

You are not taking a reference to num there. The syntax of a for loop is for PATTERN in EXPR { ... }. In patterns, the ampersand (&) is actually a dereference - patterns "match" expressions like algebra. Consider the following:

let &num = &42;

Imagine it like an algebra formula, the references "cancel out" and the statement is equivalent to:

let num = 42;
2 Likes

Patterns are not expressions.

5 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.