索引检查超出范围时分配返回值

tho*_*hor 1 rust

在伪代码中,我正在尝试以下操作:

for i in len(array):
    try:
        a = array[i-1]
    except(out_of_bounds_error):
        a = false
Run Code Online (Sandbox Code Playgroud)

其中array仅由布尔值组成。

在书中(第9.2章)中,您可以使用以下内容检查函数是否返回结果:

let a: u32 = array[i-1]
Run Code Online (Sandbox Code Playgroud)

告诉我a确实是个笨蛋。没有Result类型,如何attempt to subtract with overflow在运行时处理不可避免的(和预期的)错误?

Fra*_*gné 5

attempt to subtract with overflow计算i - 1时发生错误i == 0。数组索引必须是type usize,它是无符号类型,并且无符号类型不能表示0 - 1会产生的负数。在调试版本中,编译器会生成引发此错误的代码,而在发行版本中,编译器将生成仅计算“错误”值的代码(在这种情况下,恰好是usize::max_value())。

您可以通过执行选中的减法来避免在调试版本和发行版本中出现此错误。checked_sub返回一个OptionSome如果减法成功或None失败,您将得到一个。然后map_orOption只有在减法产生有效索引的情况下,您才能使用该方法读取数组。

fn main() {
    let a = vec![true; 10];

    for i in 0..a.len() {
        let b = i.checked_sub(1).map_or(false, |j| a[j]);
        println!("b: {}", b);
    }
}
Run Code Online (Sandbox Code Playgroud)

数组(或更确切地说,切片)还具有一种get方法,Option如果索引超出范围,则返回,而不是惊慌失措。如果我们在索引上加一,而不是减去一,那么我们可以这样做:

fn main() {
    let a = vec![true; 10];

    for i in 0..a.len() {
        let b = i.checked_add(1).and_then(|j| a.get(j).cloned()).unwrap_or(false);
        println!("b: {}", b);
    }
}
Run Code Online (Sandbox Code Playgroud)

这次,我们and_then用来将产生一个的操作Option与另一个产生的操作进行链式连接Option,并且我们unwrap_or用来获取Option的值或默认值(如果是)None