Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterating over a slice's values instead of references in Rust?

Tags:

iterator

rust

When looping over a slice of structs, the value I get is a reference (which is fine), however in some cases it's annoying to have to write var as (*var) in many places.

Is there a better way to avoid re-declaring the variable?

fn my_fn(slice: &[MyStruct]) {
    for var in slice {
        let var = *var;  // <-- how to avoid this?

        // Without the line above, errors in comments occur:

        other_fn(var);  // <-- expected struct `MyStruct`, found reference

        if var != var.other {
            // ^^ trait `&MyStruct: std::cmp::PartialEq<MyStruct>>` not satisfied
            foo();
        }
    }
}

See: actual error output (more cryptic).

like image 630
ideasman42 Avatar asked Nov 15 '16 15:11

ideasman42


Video Answer


2 Answers

You can remove the reference by destructuring in the pattern:

//  |
//  v
for &var in slice {
    other_fn(var);
}

However, this only works for Copy-types! If you have a type that doesn't implement Copy but does implement Clone, you could use the cloned() iterator adapter; see Chris Emerson's answer for more information.

like image 73
Lukas Kalbertodt Avatar answered Nov 12 '22 01:11

Lukas Kalbertodt


In some cases you can iterate directly on values if you can consume the iterable, e.g. using Vec::into_iter().

With slices, you can use cloned or copied on the iterator:

fn main() {
    let v = vec![1, 2, 3];
    let slice = &v[..];
    for u in slice.iter().cloned() {
        let u: usize = u; // prove it's really usize, not &usize
        println!("{}", u);
    }
}

This relies on the item implementing Clone or Copy, but if it doesn't you probably do want references after all.

like image 25
Chris Emerson Avatar answered Nov 12 '22 02:11

Chris Emerson