Iterating over a slice's values instead of ref

2019-02-22 03:56发布

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).

标签: iterator rust
2条回答
Bombasti
2楼-- · 2019-02-22 04:03

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:

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 obviously relies on the item being clonable; but if not you probably do want references after all.

查看更多
来,给爷笑一个
3楼-- · 2019-02-22 04:23

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 non-Copy, but Clone-only types, you could use the cloned() iterator adapter; see Chris Emerson's answer for more information. If you have types that aren't Clone, you have no chance to do it.

查看更多
登录 后发表回答