Rust流程控制:if let和while let

2023-10-18 10:40:52 浏览数 (2)

与C相比,Rust多了if let和while let这两个流程控制语句,因为之前我没有接触过这种,因此第一感觉就是有点抽象。

if let语句

先来看个具体的场景:

代码语言:javascript复制
// Make `optional` of type `Option<i32>`
let optional = Some(7);

match optional {
    Some(i) => {
        println!("This is a really long string and `{:?}`", i);
    },
    _ => {},
};

对于上面这个“只需要匹配一个分支”的场景,我们想要当optional变量为Some的时候,执行一些操作。为了实现这样的目标,我们引入了match语句。而match语句要求我们必须为其他情况编写一个处理分支,这显得不是那么的雅观。if let语句的引入正是为了改善上述代码的整洁度。

使用if let语句后,可以将上述代码等价转换为:

代码语言:javascript复制
if let Some(i) = optional {
     println!("This is a really long string and `{:?}`", i);
}

其中,上述if let语句读作:“若 letoptional 解构成 Some(i),则执行{}中的代码”。

仔细对比就可以发现,if let其实就是相当于match的简化版,它只匹配一个分支,当匹配条件不满足的时候,就不执行后面的{}中的代码。这样,我们就不用编写一个match语句了,使得代码更加整洁。

对于匹配失败的情况,我们允许在if let语句后面跟上一个else,当匹配失败时,将执行else的内容。其实就是相当于最开始的 _=> {} 分支。

代码语言:javascript复制
if let Some(i) = optional {
     println!("This is a really long string and `{:?}`", i);
}else{
     println!("failed.");
}

while let语句

与if let类似,while let语句解决的是下面这个“循环匹配一个分支“的场景中,match语句带来的复杂性的问题。

代码语言:javascript复制
// 将 `optional` 设为 `Option<i32>` 类型
let mut optional = Some(0);

// 重复运行这个测试
loop {
    match optional {
        // 如果 `optional` 解构成功,就执行下面语句块。
        Some(i) => {
            if i > 9 {
                println!("Greater than 9, quit!");
                optional = None;
            } else {
                println!("`i` is `{:?}`. Try again.", i);
                optional = Some(i   1);
            }
            // ^ 需要三层缩进!
        },
        // 当解构失败时退出循环:
        _ => { break; }
    }
}

上面的代码需要三层的缩进,看起来不是那么美观。由于我们只是想循环的匹配optional变量是Some(i)的这个种情况,在这里写loop{match{}}就有点大材小用了。

上述代码可以等价的转换为:

代码语言:javascript复制
let mut optional = Some(0);
while let Some(i) = optional {
        if i > 9 {
            println!("Greater than 9, quit!");
            optional = None;
        } else {
            println!("`i` is `{:?}`. Try again.", i);
            optional = Some(i   1);
        }
}

上述while let读作“只要let能optional 解构成 Some(i),则执行{}中的代码,直到optional不再能被解构成Some(i)为止”。所以,while let语句其实就是相当于只有一个待匹配分支的loop{match{}}语句块的功能。

参考资料:

https://doc.rust-lang.org/rust-by-example/flow_control/if_let.html

https://doc.rust-lang.org/rust-by-example/flow_control/while_let.html

0 人点赞