了解类型推理

问题描述 投票:0回答:1

我想我的数据类型和所有权都有问题。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行的计算里面,但还是有问题。

我的误解在哪里?

casting rust optional ownership inference
1个回答
1
投票

你的假设是正确的。而你的修正也是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];

会让你编译你的程序。


0
投票

你的推理是正确的。补充一下,如果你只想初始化你的数组,你也可以考虑这样做。

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 (代价是要写一个辅助函数来初始化单个元素,并说明初始化器元素,但这可以自动化,例如通过一个宏或一些辅助特征)。


0
投票

除了现有的答案之外,一个更高层次的方法也可以更简洁(取决于品味)。

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

iterCopy 所以它只是... 复制。算是吧。而且这个区块也没有用,它只包含一个简单的表达式。

© www.soinside.com 2019 - 2024. All rights reserved.