Avi*_*jit 5 iterator for-loop reference 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);
}
}
Run Code Online (Sandbox Code Playgroud)
这编译并按预期运行,但后来我指定了传递给闭包的参数的类型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);
}
}
Run Code Online (Sandbox Code Playgroud)
我收到了编译错误:
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}`
Run Code Online (Sandbox Code Playgroud)
现在,这个困惑我,直到我换k到&k的for语句,它工作得很好:
fn main() {
let my_array = [1, 2, 3];
let print_me = |j: i32| println!("= {}", j);
for &k in my_array.iter() {
print_me(k);
}
}
Run Code Online (Sandbox Code Playgroud)
似乎我误解了for语法本身 - 或者可能是迭代器的确切工作方式 - 或者可能是指针的使用语法与指针相关[在C++中相关但不同].
在结构for A in B { C1; C2; ... Cn },究竟是什么A和B应该是什么?
DK.*_*DK. 11
总而言之,B是任何表达式,它可以转换为可以转换为实现Iterator<T>特征的值的东西,同时A是一个绑定类型值的无可辩驳的模式T.
在特定情况下,slice::iter返回一个Iter<i32>,它实现了Iterator<Item = &i32>.也就是说,它不会产生i32s,它会产生&i32s.
因此,在第一和第二示例中,k实际上是绑定到&i32s而不是i32s.当您指定闭包的类型时,实际上是指定了错误的类型.最后一个例子工作的原因是因为A是一个模式,而不是一个变量名.什么&k是真正做的是"去结构化"的&i32,结合i32部分的命名变量k.
"无可辩驳的"部分仅仅意味着模式必须始终有效.例如,你不能这样做for Some(x) in thingy,其中thingy工具Iterator<Option<_>>; Some(x)对于迭代器中的每个元素都不一定有效; 因此,它是一种可反复的模式.
许多迭代器实际上返回一个引用而不是一个值.可以肯定的是,你必须检查返回类型.iter(),它应该是以下形式Iterator<Item = X>: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);
}
}
Run Code Online (Sandbox Code Playgroud)
这X是&i32(引用i32),因此k具有类型&i32.
这就是为什么在调用print_me时会出现错误:&i32传递到i32期望的位置.
这里有多种可能的修复方法:
指定不同的类型print_me:
let print_me = |j: &i32| println!("= {}", j);
Run Code Online (Sandbox Code Playgroud)取消引用的价值k:
print_me(*k);
Run Code Online (Sandbox Code Playgroud)k通过循环中的解构来改变类型:
for &k in my_array.iter() { ... }
Run Code Online (Sandbox Code Playgroud)进行解构是因为for .. 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)
}
}
Run Code Online (Sandbox Code Playgroud)
类型my_array是[(i32, i32)]:2的元组数组i32.的结果.iter()因此是类型的Iterator<Item = &(i32, i32)>:一个迭代到2元组的参考i32又名&(i32, i32).
当我们使用无可辩驳的模式时&(j, k),发生的是我们对元组进行解构,以便:
j(推断为类型i32,只有因为i32是Copy)k((推断为类型i32)j并k因此成为的临时副本i32内这个元素.
| 归档时间: |
|
| 查看次数: |
748 次 |
| 最近记录: |