我想我的数据类型和所有权都有问题。iter
. 它首先在 for
循环表达式。我相信Rust会推断出 iter
属于 u16
因为它在我的第4行的计算中被使用。
1 let mut numbers: [Option<u16>; 5];
2 for iter in 0..5 {
3 let number_to_add: u16 = { // `iter` moves to inner scope
4 ((iter * 5) + 2) / (4 * 16) // Infers `iter: u16`
5 };
6
7 numbers[iter] = Some(number_to_add); // Expects `iter: usize`
8 }
我收到以下错误。
error[E0277]: the type `[std::option::Option<u16>]` cannot be indexed by `u16`
--> exercises/option/option1.rs:3:9
|
7 | numbers[iter] = Some(number_to_add);
| ^^^^^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
iter
作为 u16
在第4行的计算里面,但还是有问题。我的误解在哪里?
你的假设是正确的。而你的修正也是OK的(它导致了一个不同的错误,见下文)。
你的第一个问题是,对于分片索引,iter需要是类型为 usize
所以要么
numbers[iter as usize] = Some(number_to_add);
或
((iter as u16 * 5) + 2) / (4 * 16)
将导致通过rustc进行正确的类型推断。
你的第二个问题是数字没有被初始化,所以当你试图修改数字时,rustc会正确地警告你。赋一个值,例如。
let mut numbers: [Option<u16>; 5] = [None; 5];
会让你编译你的程序。
你的推理是正确的。补充一下,如果你只想初始化你的数组,你也可以考虑这样做。
let arr_elem = |i: u16| Some(((i * 5) + 2) / (4 * 16));
let numbers : [Option<u16>; 5] = [
arr_elem(0),
arr_elem(1),
arr_elem(2),
arr_elem(3),
arr_elem(4),
];
这样一来,你就不需要让它 mut
(代价是要写一个辅助函数来初始化单个元素,并说明初始化器元素,但这可以自动化,例如通过一个宏或一些辅助特征)。
除了现有的答案之外,一个更高层次的方法也可以更简洁(取决于品味)。
let mut numbers = [None; 5];
for (i, n) in numbers.iter_mut().enumerate() {
let iter = i as u16;
let number_to_add: u16 =
((iter * 5) + 2) / (4 * 16);
*n = Some(number_to_add);
}
另一种选择是一种更懒惰的方法,但没有办法(fafaik)将例如 try_collect
变成一个数组,只有 try_from
分片到一个数组,所以你需要将collect()转换成一个vec,然后将 try_from
到一个数组,这似乎不太有用。虽然你可以使用迭代器来初始化你的数组。
let mut it = (0u16..5).map(|i| ((i * 5) + 2) / (4 * 16));
let numbers = [it.next(), it.next(), it.next(), it.next(), it.next()];
也可以
// `iter` moves to inner scope
iter
是 Copy
所以它只是... 复制。算是吧。而且这个区块也没有用,它只包含一个简单的表达式。