我有 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_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);
}
}
编译错误:
error[E0308]: mismatched types
--> src/main.rs:6:22
|
6 | print_me(k);
| ^
| |
| expected i32, found &{integer}
| help: consider dereferencing the borrow: `*k`
|
= note: expected type `i32`
found type `&{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);
}
}
我似乎误解了 for
语法本身——或者可能是迭代器的确切工作原理——或者可能是引用相对于指针的使用语法 [这是相关的但在 C++ 中是不同的]。
在构造 for A in B { C1; C2; ... Cn
,A
和 B
到底应该是什么?
最佳答案
首先,这里有一个链接 the definition of for
in the reference .
总结一下,B
是任何表达式,其计算结果可以转换为实现 Iterator<T>
的值特征,同时 A
是一个无可辩驳的模式,它绑定(bind)了 T
类型的值。 .
在您的具体情况下, slice::iter
返回 Iter<i32>
,这implements Iterator<Item = &i32>
.也就是说,它不会产生 i32
s, 它产生 &i32
因此,在第一个和第二个示例中,k
实际上绑定(bind)到 &i32
s,不是 i32
秒。当您指定闭包的类型时,您实际上是在指定错误的类型。最后一个例子起作用的原因是因为 A
是一个模式,不是变量名。什么&k
实际上正在“解构”&i32
, 绑定(bind) i32
部分到名为 k
的变量.
“无可辩驳”部分只是意味着该模式必须始终 有效。例如,你不能做 for Some(x) in thingy
其中 thingy
工具 Iterator<Option<_>>
; Some(x)
不一定对迭代器中的每个元素都有效;因此,这是一个可反驳的模式。
关于for-loop - Rust 中 for 循环的确切定义是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27224927/