Rust 流程控制

  |   0 评论   |   0 浏览

条件选择

if 条件选择是一个表达式(可以用来赋值),并且所有分支都必须返回相同的类型。
判断条件不必用小括号括起来,条件后跟的代码块必须用大括号括起来。

示例一:if 表达式

1fn main() {
2    let number = 3;
3
4    if number != 0 {
5        println!("number was something other than zero");
6    }
7}

示例二:if-else 表达式

1fn main() {
2    let number = 3;
3
4    if number < 5 {
5        println!("condition was true");
6    } else {
7        println!("condition was false");
8    }
9}

示例三:if-else-if 表达式

 1fn main() {
 2    let n = 5;
 3
 4    if n < 0 {
 5        println!("{} is negative", n);
 6    } else if n > 0 {
 7        println!("{} is positive", n);
 8    } else {
 9        println!("{} is zero", n);
10    }
11}

循环语句

Rust 提供了三种循环:loopwhilefor

loop 循环

无限循环,一般配合break表达式使用。

示例

 1fn main() {
 2    // 这是一个无限循环
 3    loop {
 4        println!("again!");
 5    }
 6
 7    let mut counter = 0;
 8
 9    let result = loop {
10        counter += 1;
11        // 设置循环终止条件,并返回一个结果
12        if counter == 10 {
13            break counter * 2;
14        }
15    };
16
17    println!("The result is {}", result);
18}

while 循环

示例

 1fn main() {
 2    let mut number = 3;
 3
 4    while number != 0 {
 5        println!("{}!", number);
 6        number = number - 1;
 7    }
 8
 9    println!("LIFTOFF!!!");
10}

for 循环

示例

 1fn main() {
 2    // `n` 的值为: 1, 2, ..., 100(`1..101` 等价于 `1..=100`)
 3    for n in 1..101 {
 4        if n % 15 == 0 {
 5            println!("fizzbuzz");
 6        } else if n % 3 == 0 {
 7            println!("fizz");
 8        } else if n % 5 == 0 {
 9            println!("buzz");
10        } else {
11            println!("{}", n);
12        }
13    }
14
15    let a = [10, 20, 30, 40, 50];
16    // 使用 for 循环遍历集合中的元素
17    for element in a.iter() {
18        println!("the value is: {}", element);
19    }
20}

模式匹配

Rust 通过 match 关键字提供了模式匹配功能,类似于 C 中的 switch,但功能更强大。

match 表达式由 match 关键字、用于匹配的值和一个或多个分支构成,每个分支包含一个模式(pattern)以及一个待执行的表达式。

1match VALUE {
2    PATTERN1 => EXPRESSION1,
3    PATTERN2 => EXPRESSION2,
4    PATTERN3 => EXPRESSION3,
5    ...
6    PATTERNn => EXPRESSIONn,
7}

执行过程:依次将 PATTERN1PATTERN2... 和 VALUE 进行比对,一旦匹配成功就执行该分支中 => 后面的表达式,并且不再继续匹配后面的分支。其中,PATTERNn 可以是字面量、元组、枚举、结构体、通配符、函数等。

模式匹配的要求:

  • 所有分支必须穷举所有的可能。
  • 每个分支必须是一个表达式,且通常这些表达式的返回值类型必须相同。

示例

 1enum Direction {
 2    East,
 3    West,
 4    North,
 5    South,
 6}
 7fn main() {
 8    let d_west = Direction::West;
 9    let d_str = match d_west {
10        Direction::East => "East",
11        Direction::North | Direction::South => {
12            panic!("South or North");
13        }, // 该分支一定会触发 panic,返回值类型可以与其他分支不同
14        _ => "West",
15    };
16    println!("{}", d_str);
17}

解构

当待匹配的模式是复合类型时,可以提取复合类型值中的部分数据。

示例一:解构元组

 1fn main() {
 2    let triple = (0, -2, 3);
 3
 4    println!("Tell me about {:?}", triple);
 5
 6    match triple {
 7        // 解构元组中第2和第3个元素
 8        (0, y, z) => println!("First is `0`, `y` is {:?}, and `z` is {:?}", y, z),
 9        // 使用 `..` 忽略其他元素,仅匹配第1个元素
10        (1, ..)  => println!("First is `1` and the rest doesn't matter"),
11        // `_` 匹配所有值,通常将它放在最后,用来匹配剩余的所有可能值
12        _      => println!("It doesn't matter what they are"),
13    }
14}

示例二:解构枚举

 1#[allow(dead_code)]
 2enum Color {
 3    Red,
 4    Blue,
 5    Green,
 6    RGB(u32, u32, u32),
 7    HSV(u32, u32, u32),
 8    HSL(u32, u32, u32),
 9    CMY(u32, u32, u32),
10    CMYK(u32, u32, u32, u32),
11}
12
13fn main() {
14    let color = Color::RGB(122, 17, 40);
15
16    println!("What color is it?");
17
18    match color {
19        Color::Red   => println!("The color is Red!"),
20        Color::Blue  => println!("The color is Blue!"),
21        Color::Green => println!("The color is Green!"),
22        Color::RGB(r, g, b) =>
23            println!("Red: {}, green: {}, and blue: {}!", r, g, b),
24        Color::HSV(h, s, v) =>
25            println!("Hue: {}, saturation: {}, value: {}!", h, s, v),
26        Color::HSL(h, s, l) =>
27            println!("Hue: {}, saturation: {}, lightness: {}!", h, s, l),
28        Color::CMY(c, m, y) =>
29            println!("Cyan: {}, magenta: {}, yellow: {}!", c, m, y),
30        Color::CMYK(c, m, y, k) =>
31            println!("Cyan: {}, magenta: {}, yellow: {}, key (black): {}!", c, m, y, k),
32    }
33}

示例三:解构结构体

 1fn main() {
 2    struct Foo {
 3        x: (u32, u32),
 4        y: u32,
 5    }
 6
 7    let foo = Foo { x: (1, 2), y: 3 };
 8
 9    match foo {
10        Foo { x: (1, b), y } => println!("First of x is 1, b = {},  y = {} ", b, y),
11
12        // 可以对字段(field)重命名
13        Foo { y: 2, x: i } => println!("y is 2, i = {:?}", i),
14        // Foo { y: 2, x } => println!("y is 2, i = {:?}", x),
15
16        // 可以使用 `..` 忽略一些字段(field)
17        Foo { y, .. } => println!("y = {}, we don't care about x", y),
18    }
19}

示例四:匹配范围

 1fn main() {
 2    let x = 1;
 3    match x {
 4        1 ..=10 => println!("一到十"),
 5        _ => println!("其它"),
 6    }
 7
 8    let c = 'w';
 9    match c {
10        'a' ..='z' => println!("小写字母"),
11        'A' ..='Z' => println!("大写字母"),
12        _ => println!("其他字符"),
13    }
14}

示例五:多重匹配

1fn main() {
2    let x = 1;
3    // 匹配多个模式时,使用 `|` 分隔
4    match x {
5        1 | 2 => println!("一或二"),
6        _ => println!("其他"),
7    }
8}

后置条件

一个 if 表达式可以被放在 match 的模式之后,被称为 match guard

示例

1fn main() {
2    let x = 4;
3    let y = false;
4    match x {
5        4 | 5 if y => println!("yes"),
6        _ => println!("no"),
7    }
8}

绑定

可以使用 @ 符号将模式中匹配的值绑定一个名称,详细说明见Identifier patterns

示例

 1fn age() -> u32 {
 2    15
 3}
 4
 5fn main() {
 6    println!("Tell me what type of person you are");
 7
 8    match age() {
 9        0             => println!("I haven't celebrated my first birthday yet"),
10        n @ 1  ..= 12 => println!("I'm a child of age {:?}", n),
11        n @ 13 ..= 19 => println!("I'm a teen of age {:?}", n),
12        // Nothing bound. Return the result.
13        n             => println!("I'm an old person of age {:?}", n),
14    }
15}

if let

在某些情况下,可以使用 if let 对模式匹配进行简化。

示例

 1fn main() {
 2    let number = Some(7);
 3    let letter: Option<i32> = None;
 4
 5    match number {
 6        Some(i) => {
 7            println!("Matched {:?}!", i);
 8        }
 9        _ => {} // 此分支什么都不做,但是不能省略,因为模式匹配要列举所有可能
10    };
11
12    // 可以将上面的模式匹配该为下面这种形式
13    if let Some(i) = number {
14        println!("Matched {:?}!", i);
15    }
16
17    // 如果需要对未匹配的情况进行处理,还可以添加 `else` 分支
18    if let Some(i) = letter {
19        println!("Matched {:?}!", i);
20    } else {
21        println!("Didn't match a number. Let's go with a letter!");
22    }
23}

while let

if let 类似,使用 while let 也可以对模式匹配进行简化,只关注要匹配的值,其它的值不用做显式处理。

示例

 1fn main() {
 2    let mut optional = Some(0);
 3
 4    loop {
 5        match optional {
 6            Some(i) => {
 7                if i > 9 {
 8                    println!("Greater than 9, quit!");
 9                    optional = None;
10                } else {
11                    println!("`i` is `{:?}`. Try again.", i);
12                    optional = Some(i + 1);
13                }
14            }
15            _ => {
16                break;
17            }
18        }
19    }
20
21    // 上面loop中的模式匹配可以改为下面这种形式
22    while let Some(i) = optional {
23        if i > 9 {
24            println!("Greater than 9, quit!");
25            optional = None; // 这是循环结束条件
26        } else {
27            println!("`i` is `{:?}`. Try again.", i);
28            optional = Some(i + 1);
29        }
30    }
31}

相关资料

The Rust Programming Language

The Rust Reference

Rust by Example