控制流(control flow)

If

If是分支 (branch) 的一种特殊形式,也可以使用elseelse if
与C语言不同的是,逻辑条件不需要用小括号括起来,但是条件后面必须跟一个代码块。
Rust中的if是一个表达式 (expression),可以赋给一个变量:

  1. let x = 5;
  2. let y = if x == 5 { 10 } else { 15 };

Rust是基于表达式的编程语言,有且仅有两种语句 (statement):

  1. 声明语句 (declaration statement),比如进行变量绑定的let语句。
  2. 表达式语句 (expression statement),它通过在末尾加上分号;来将表达式变成语句,
    丢弃该表达式的值,一律返回unit()

表达式如果返回,总是返回一个值,但是语句不返回值或者返回(),所以以下代码会报错:

  1. let y = (let x = 5);
  2. let z: i32 = if x == 5 { 10; } else { 15; };

值得注意的是,在Rust中赋值 (如x = 5) 也是一个表达式,返回unit的值()

For

Rust中的for循环与C语言的风格非常不同,抽象结构如下:

  1. for var in expression {
  2. code
  3. }

其中expression是一个迭代器 (iterator),具体的例子为0..10 (不包含最后一个值),
或者[0, 1, 2].iter()

While

Rust中的while循环与C语言中的类似。对于无限循环,Rust有一个专用的关键字loop
如果需要提前退出循环,可以使用关键字break或者continue
还允许在循环的开头设定标签 (同样适用于for循环):

  1. 'outer: loop {
  2. println!("Entered the outer loop");
  3. 'inner: loop {
  4. println!("Entered the inner loop");
  5. break 'outer;
  6. }
  7. println!("This point will never be reached");
  8. }
  9. println!("Exited the outer loop");

Match

Rust中的match表达式非常强大,首先看一个例子:

  1. let day = 5;
  2. match day {
  3. 0 | 6 => println!("weekend"),
  4. 1 ... 5 => println!("weekday"),
  5. _ => println!("invalid"),
  6. }

其中|用于匹配多个值,...匹配一个范围 (包含最后一个值),并且_在这里是必须的,
因为match强制进行穷尽性检查 (exhaustiveness checking),必须覆盖所有的可能值。
如果需要得到|或者...匹配到的值,可以使用@绑定变量:

  1. let x = 1;
  2. match x {
  3. e @ 1 ... 5 => println!("got a range element {}", e),
  4. _ => println!("anything"),
  5. }

使用ref关键字来得到一个引用:

  1. let x = 5;
  2. let mut y = 5;
  3. match x {
  4. // the `r` inside the match has the type `&i32`
  5. ref r => println!("Got a reference to {}", r),
  6. }
  7. match y {
  8. // the `mr` inside the match has the type `&i32` and is mutable
  9. ref mut mr => println!("Got a mutable reference to {}", mr),
  10. }

再看一个使用match表达式来解构元组的例子:

  1. let pair = (0, -2);
  2. match pair {
  3. (0, y) => println!("x is `0` and `y` is `{:?}`", y),
  4. (x, 0) => println!("`x` is `{:?}` and y is `0`", x),
  5. _ => println!("It doesn't matter what they are"),
  6. }

match的这种解构同样适用于结构体或者枚举。如果有必要,还可以使用..来忽略域或者数据:

  1. struct Point {
  2. x: i32,
  3. y: i32,
  4. }
  5. let origin = Point { x: 0, y: 0 };
  6. match origin {
  7. Point { x, .. } => println!("x is {}", x),
  8. }
  9. enum OptionalInt {
  10. Value(i32),
  11. Missing,
  12. }
  13. let x = OptionalInt::Value(5);
  14. match x {
  15. // 这里是 match 的 if guard 表达式,我们将在以后的章节进行详细介绍
  16. OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
  17. OptionalInt::Value(..) => println!("Got an int!"),
  18. OptionalInt::Missing => println!("No such luck."),
  19. }

此外,Rust还引入了if letwhile let进行模式匹配:

  1. let number = Some(7);
  2. let mut optional = Some(0);
  3. // If `let` destructures `number` into `Some(i)`, evaluate the block.
  4. if let Some(i) = number {
  5. println!("Matched {:?}!", i);
  6. } else {
  7. println!("Didn't match a number!");
  8. }
  9. // While `let` destructures `optional` into `Some(i)`, evaluate the block.
  10. while let Some(i) = optional {
  11. if i > 9 {
  12. println!("Greater than 9, quit!");
  13. optional = None;
  14. } else {
  15. println!("`i` is `{:?}`. Try again.", i);
  16. optional = Some(i + 1);
  17. }
  18. }