4
votes

What can I do to iterate over an array of integers in Rust?

fn main () {

    let mut array: Vec<i64> = vec![2];

    for k in range(3, 13195) {
        for p in array.iter() {
           if (k % p != 0) {array.push(p)};
        }        
    }
}

Gives me the compiler error:

rustc "Task2_minimalcode.rs" (im Verzeichnis: C:\Users\XXX\Documents\Rust - Project Euler)

Task2_minimalcode.rs:7:14: 7:15 error: mismatched types: expected _, found &i64 (expected integral variable, found &-ptr) [E0308] Task2_minimalcode.rs:7 if (k % p != 0) {array.push(p)};
^ Task2_minimalcode.rs:7:34: 7:35 error: mismatched types: expected i64, found &i64 (expected i64, found &-ptr) [E0308]

Task2_minimalcode.rs:7 if (k % p != 0) {array.push(p)}; ^ error: aborting due to 2 previous errors Failed compilation.

2

2 Answers

4
votes

Quoth the error message:

error: mismatched types: expected i64, found &i64 (expected i64, found &-ptr)

Vec<T>::iter gives you an iterator over &T (references to T). If you don't intend to ever use the vec again, you can use for p in array or for p in array.into_iter(). If you do want to use it again, you have several options:

  • &array or array.iter(), and dereference p when using it.
  • array.iter().cloned()
  • array.iter().map(|e| *e) (effectively the same as above)

If all this talk about references doesn't make sense, you should probably read the section of the Rust Book on Pointers.

Remember that you can trick the compiler into telling you the type of a variable like so: let _:() = p; -- the error message will contain the true type.

1
votes

When you iterate over a slice (which is a view into the Vec), you are getting references to the items in the vector, not the items themselves.

You can fix that in two equivalent ways.

// Mark the iteration variable as a reference
for &p in &array {
    if (k % p != 0) {
        array.push(p)
    };
}

// Dereference the iteration variable
for p in &array {
    if (k % *p != 0) {
        array.push(*p)
    };
}

However, then you run into the next problem: you can't modify the Vec while you are iterating over it! If you were allowed to, the vector might need to reallocate the memory that backs it, which would then in turn invalidate all of the references in the iterator. This is a strong selling point of Rust - it prevents you from shooting yourself in the foot like this!

Without knowing what you really want to do, here's one way of doing it:

fn main() {
    let input_array = vec![2u64];
    let mut output_array = input_array.clone();

    for k in 3..13195 {
        for &p in &input_array {
            if k % p != 0 {
                output_array.push(p)
            };
        }
    }
}

See also: