For loop Rust中for循环的确切定义是什么?

For loop Rust中for循环的确切定义是什么?,for-loop,reference,iterator,rust,For Loop,Reference,Iterator,Rust,我来自C(在较小程度上是C++)背景。我编写了以下代码片段: fn main() { let my_array = [1, 2, 3]; let print_me = |j| println!("= {}", j); for k in my_array.iter() { print_me(k); } } 这是按预期编译和运行的,但随后我指定了传递给闭包的参数类型print\u me,因此: fn main() { let my_array

我来自C(在较小程度上是C++)背景。我编写了以下代码片段:

fn main() {
    let my_array = [1, 2, 3];
    let print_me = |j| println!("= {}", j);
    for k in my_array.iter() {
        print_me(k);
    }
}
这是按预期编译和运行的,但随后我指定了传递给闭包的参数类型
print\u me
,因此:

fn main() {
    let my_array = [1, 2, 3];
    let print_me = |j: i32| println!("= {}", j);
    for k in my_array.iter() {
        print_me(k);
    }
}
我得到一个编译错误:

错误[E0308]:类型不匹配
-->src/main.rs:6:22
|
6 |打印(k);
|                      ^
|                      |
|应为i32,找到&{integer}
帮助:考虑取消借阅:'*k '
|
=注意:应为'i32'类型`
找到类型`&{integer}`
现在这让我很困惑,直到我在
for
语句中将
k
改为
&k
,效果很好:

fn main() {
    let my_array = [1, 2, 3];
    let print_me = |j: i32| println!("= {}", j);
    for &k in my_array.iter() {
        print_me(k);
    }
}
似乎我误解了
语法本身,或者可能是迭代器的确切工作方式,或者可能是引用相对于指针的用法语法[在C++中是相关但不同的]


在B{C1;C2;…Cn}
中A的构造
中,
A
B
到底应该是什么?

首先,这里是到的链接

总之,
B
是任何表达式,其计算结果可以转换为实现
迭代器
特性的值,而
a
是一种无可辩驳的模式,它绑定了
T
类型的值

在您的特定情况下,返回一个。也就是说,它不会产生
i32
s,而是产生
&i32
s

因此,在第一和第二示例中,
k
实际上绑定到
&i32
s,而不是
i32
s。指定闭包的类型时,实际上指定了错误的类型。最后一个示例之所以有效,是因为
A
是一种模式,而不是变量名。
&k
实际上所做的是对
&i32
进行“去结构化”,将
i32
部分绑定到名为
k
的变量


“无可辩驳”部分仅仅意味着模式必须始终有效。例如,您不能对thingy中的某些(x)执行
,其中
thingy
实现了
Iterator
Some(x)
不一定对迭代器中的每个元素都有效;因此,这是一个可反驳的模式。

许多迭代器实际上返回一个引用而不是一个值。当然,您必须检查
.iter()
的返回类型,它应该是
迭代器的形式:
X
将是返回的变量的类型

因此,这里:

fn main() {
    let my_array = [1, 2, 3];
    let print_me = |j: i32| println!("= {}", j);
    for k in my_array.iter() {
        print_me(k);
    }
}
X
&i32
(对
i32
的引用),因此
k
具有类型
&i32

这就是为什么在调用
print\u me
时出现错误:
&i32
在预期的
i32
位置传递


这里有多个可能的修复:

  • 指定要打印的不同类型:

    let print_me = |j: &i32| println!("= {}", j);
    
  • 取消引用
    k的值

    print_me(*k);
    
  • 通过在循环中分解结构来更改
    k
    的类型:

    for &k in my_array.iter() { ... }
    
  • 由于..的
    。。in
    接受一个无可辩驳的模式,因此可以像在
    match
    表达式中一样进行模式匹配,但变量的类型必须匹配(否则会出现编译器时间错误)

    为了更好地说明这一点,我们可以使用稍微复杂一点的示例:

    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)
        }
    }
    
    my_数组的类型是
    [(i32,i32)]
    :一个2的元组数组
    i32
    。因此,
    .iter()
    的结果属于类型
    迭代器
    :对2的元组引用的迭代器
    i32
    aka
    &(i32,i32)

    当我们使用无可辩驳的模式
    &(j,k)
    时,我们会对元组进行分解,以便:

    • 第一个元素绑定到
      j
      (推断为
      i32
      类型,仅因为
      i32
      Copy
    • 第二个元素绑定到
      k
      ((推断为类型
      i32
    j
    k
    因此成为该元素内
    i32
    的临时副本