What is the exact definition of the for loop in Rust?

后端 未结 2 1565
轻奢々
轻奢々 2020-12-20 19:33

I\'m coming from a C (and to a lesser extent, C++) background. I wrote the following code snippet:

fn main() {
    let my_array = [1, 2, 3];
    let print_me         


        
2条回答
  •  一向
    一向 (楼主)
    2020-12-20 19:56

    Many iterators actually return a reference rather than a value. To be sure, you have to check the return type of .iter(), which should be of the form Iterator: X will be the type of the variable returned.

    So here:

    fn main() {
        let my_array = [1, 2, 3];
        let print_me = |j: i32| println!("= {}", j);
        for k in my_array.iter() {
            print_me(k);
        }
    }
    

    This X is &i32 (a reference to i32), and therefore k has type &i32.

    This is why, when calling print_me, there is an error: &i32 is passed where i32 is expected.


    There are multiple possible fixes here:

    1. specify a different type to print_me:

      let print_me = |j: &i32| println!("= {}", j);
      
    2. dereference the value of k:

      print_me(*k);
      
    3. change the type of k by destructuring in the loop:

      for &k in my_array.iter() { ... }
      

    The destructuring occurs because for .. in accepts an irrefutable pattern, so you can pattern match like you would do in a match expression, except that the variable's type has to match (otherwise you get a compiler time error).

    To better illustrate it, we can use a slightly more complicated example:

    fn main() {
        let my_array = [(1, 2), (2, 3), (3, 4)];
        let print_me = |a: i32, b: i32| println!("= {} {}", a, b);
        for &(j, k) in my_array.iter() {
            print_me(j, k)
        }
    }
    

    The type of my_array is [(i32, i32)]: an array of tuples of 2 i32. The result of .iter() is therefore of type Iterator: an iterator to a reference to a tuple of 2 i32 aka &(i32, i32).

    When we use the irrefutable pattern &(j, k) what happens is that we destructure the tuple so that:

    • the first element binds to j (inferred to be of type i32, only works because i32 is Copy)
    • the second element binds to k ((inferred to be of type i32)

    j and k thus become temporary copies of the i32 inside this element.

提交回复
热议问题