# 流控制

### if/else

``````fn main() {
let n = 5;

if n < 0 {
print!("{} is negative", n);
} else if n > 0 {
print!("{} is positive", n);
} else {
print!("{} is zero", n);
}

let big_n =
if n < 10 && n > -10 {
println!(", and is a small number, increase ten-fold");

// 表达式返回一个 `i32`.
10 * n
} else {
println!(", and is a big number, reduce by two");
n / 2
};
//   ^ 别忘记要加一个分号，所有的绑定语句都要加上分号

println!("{} -> {}", n, big_n);
}
``````

### 循环

Rust提供 `loop` 关键字来指定无限循环。

`break` 语句可在任意时刻中断循环, `continue` 语句能跳过该循环剩余部分并继续执行下一循环。

``````fn main() {
let mut count = 0u32;
println!("Let's count until infinity!");
loop {
count += 1;

if count == 3 {
println!("three");
continue;
}

println!("{}", count);

if count == 5 {
println!("OK, that's enough");
break;
}
}
}
``````
##### 嵌套循环和标签

``````#![allow(unreachable_code)]

fn main() {
'outer: loop {
println!("Entered the outer loop");
'inner: loop {
println!("Entered the inner loop");
// This would break only the inner loop
//break;
// This breaks the outer loop
break 'outer;
}
println!("This point will never be reached");
}
println!("Exited the outer loop");
}
``````

### while

`while` 关键字能够在满足特定条件的时候停止循环。

Players take turns to count incrementally, replacing any number divisible by three with the word "fizz", and any number divisible by five with the word "buzz".

``````fn main() {
let mut i = 1;
while i != 100 {
if i % 15 == 0 {
println!("Fizzbuzz");
}
else if i % 3  == 0{
println!("Fizz");
}
else if i % 5 == 0{
println!("Buzz");
}
else {
println!("{}", i);
}
i += 1;
}
}
``````

### for 和范围

`for` 结构能够用于迭代迭代器。构造迭代器最简单的方法就是使用范围 `a..b`。范围包含 `a` 但不包含 `b`

`for` 循环写一个 `FizzBuzz`

``````fn main() {
let mut i = 1;

for i in 1..101 {
if i % 15 == 0 {
println!("Fizzbuzz");
}
else if i % 3  == 0{
println!("Fizz");
}
else if i % 5 == 0{
println!("Buzz");
}
else {
println!("{}", i);
}
}
}
``````

### 匹配

Rust通过 `match` 关键字提供了模式匹配，好比C语言中的 `switch` 关键字。

``````fn main() {
let number = 13;
match number {
// 匹配单值
1 => println!("One!"),
// 匹配多值
2 | 3 | 5 | 7 | 11 => println!("This is a prime"),
// 匹配范围
13...19 => println!("A teen"),
// 匹配剩余
_ => println!("Ain't special"),
}

let boolean = true;
// Match is an expression too
let binary = match boolean {
// 必须覆盖分支所有可能性
false => 0,
true => 1,
};

println!("{} -> {}", boolean, binary);
}
``````
##### 析构

`match` 代码块能以析构多种结构。

###### 元组

``````fn main() {
let pair = (0, -2);
// 用于析构元组
match pair {
// Destructure the second
(0, y) => println!("First is `0` and `y` is `{:?}`", y),
(x, 0) => println!("`x` is `{:?}` and last is `0`", x),
_      => println!("It doesn't matter what they are"),
// `_` means don't bind the value to a variable
}
}
``````
###### 枚举
``````#[allow(dead_code)]
enum Color {
// These 3 are specified solely by their name.
Red,
Blue,
Green,
// These likewise tie `u32` tuples to different names: color models.
RGB(u32, u32, u32),
HSV(u32, u32, u32),
HSL(u32, u32, u32),
CMY(u32, u32, u32),
CMYK(u32, u32, u32, u32),
}

fn main() {
let color = Color::RGB(122, 17, 40);
// TODO ^ Try different variants for `color`

println!("What color is it?");
// 用 `match` 可以析构 `enum`
match color {
Color::Red   => println!("The color is Red!"),
Color::Blue  => println!("The color is Blue!"),
Color::Green => println!("The color is Green!"),
Color::RGB(r, g, b) =>
println!("Red: {}, green: {}, and blue: {}!", r, g, b),
Color::HSV(h, s, v) =>
println!("Hue: {}, saturation: {}, value: {}!", h, s, v),
Color::HSL(h, s, l) =>
println!("Hue: {}, saturation: {}, lightness: {}!", h, s, l),
Color::CMY(c, m, y) =>
println!("Cyan: {}, magenta: {}, yellow: {}!", c, m, y),
Color::CMYK(c, m, y, k) =>
println!("Cyan: {}, magenta: {}, yellow: {}, key (black): {}!",
c, m, y, k),
// Don't need another arm because all variants have been examined
}
}
``````
###### 指针/引用

• 解引用用 `*`
• 析构用 `&`, `ref`, 及 `ref mut`
``````fn main() {
// 分配一个 `i32` 类型的引用. `&` 说明有一个引用被分配。
let reference = &4;

match reference {
// 如果 `reference`s 匹配为 `&val`, 会产生如下的比较
// `&i32`
// `&val`
// 我们看到，如果匹配的 `&` 都去掉了，那么就是 `i32` 赋给 `val`。
&val => println!("Got a value via destructuring: {:?}", val),
}

// 避免 `&`, 在匹配之前解引用
match *reference {
val => println!("Got a value via dereferencing: {:?}", val),
}

// 如果没有一个引用头部（以 & 开头）会是怎样？ `reference` 是一个 `&`，
// 因为右边已经是一个引用。下面这个不是引用，因为右边不是。
let _not_a_reference = 3;

// Rust 提供了关键字 `ref`。修改了赋值以致为元素创建引用
let ref _is_a_reference = 3;

// 可以通过 `ref` 和 `ref mut` 获取引用
let value = 5;
let mut mut_value = 6;

// 使用 `ref` 关键字创建引用
match value {
ref r => println!("Got a reference to a value: {:?}", r),
}
match mut_value {
ref mut m => {
// 得到引用，只有解引用才能进行加法操作
*m += 10;
println!("We added 10. `mut_value`: {:?}", m);
},
}
}
``````
###### 结构

``````fn main() {
struct Foo { x: (u32, u32), y: u32 }

// 析构结构成员
let foo = Foo { x: (1, 2), y: 3 };
let Foo { x: (a, b), y } = foo;

println!("a = {}, b = {},  y = {} ", a, b, y);

// 你可以析构并重名变量
// 顺序并不重要

let Foo { y: i, x: j } = foo;
println!("i = {:?}, j = {:?}", i, j);

// 也可以忽视某些变量
let Foo { y, .. } = foo;
println!("y = {}", y);

// 但是这样就会产生错误：模式中没有提及 `x`
// let Foo { y } = foo;
}
``````
##### 守卫

`match` 守卫能添加用于过滤分支。

``````fn main() {
let pair = (2, -2);
match pair {
(x, y) if x == y => println!("These are twins"),
// The ^ `if condition` part is a guard
(x, y) if x + y == 0 => println!("Antimatter, kaboom!"),
(x, _) if x % 2 == 1 => println!("The first one is odd"),
_ => println!("No correlation..."),
}
}
``````
##### 绑定

``````// `age` 函数，返回一个 `u32` 值。
fn age() -> u32 {
15
}

fn main() {
println!("Tell me type of person you are");

match age() {
0             => println!("I'm not born yet I guess"),
// 不能直接 `匹配（match）` 1 ... 12，但是孩子是几岁呢？
// 相反，将 1 ... 12 序列绑定到 `n` 。现在年龄就可以读取了。
n @ 1  ... 12 => println!("I'm a child of age {:?}", n),
n @ 13 ... 19 => println!("I'm a teen of age {:?}", n),
// 没有绑定。返回结果。
n             => println!("I'm an old person of age {:?}", n),
}
}
``````

### if let

``````// 使 `optional` 使用类型 `Option<i32>`
let optional = Some(7);

match optional {
Some(i) => {
println!("This is a really long string and `{:?}`", i);
// ^ 行首需要2个缩进，就这样可以从 option 类型中对 `i`
// 进行解构
},
_ => {},
// ^ 必需内容，因为 `match` 需要覆盖全部情况。难道不觉得冗余吗？
};
``````

`if let` 对这样的用法要简洁得多，并且允许指明特定的各种不同的失败可选项 内容（options）：

``````fn main() {
// 全部都是 `Option<i32>` 类型
let number = Some(7);
let letter: Option<i32> = None;
let emoticon: Option<i32> = None;

// `if let` 结构解读：若 `let` 将 `number` 解构成 `Some(i)`，则执行
// 语句块（`{}`）
if let Some(i) = number {
println!("Matched {:?}!", i);
}

// 如果要指明失败情形，就使用 else：
if let Some(i) = letter {
println!("Matched {:?}!", i);
} else {
// 解构失败。换到失败情形（Change to the failure case）。
println!("Didn't match a number. Let's go with a letter!");
};

// 提供一个改变的失败条件（Provide an altered failing condition）。
let i_like_letters = false;

if let Some(i) = emoticon {
println!("Matched {:?}!", i);
// 解构失败。执行 `else if` 条件来判断轮到的失败分支是否需要执行
} else if i_like_letters {
println!("Didn't match a number. Let's go with a letter!");
} else {
// 条件执行错误。这是默认的分支：
println!("I don't like letters. Let's go with an emoticon :)!");
};
}
``````

### while let

`if let` 类似，`while let` 会产生更加难看的 `match` 的一连串内容。 考虑下面的有关增量 `i` 的一连串内容：

``````// 将 `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; }
// ^ 为什么要这样的语句呢？肯定有更优雅的处理方式！
}
}
``````

``````fn main() {
// 将 `optional` 设为 `Option<i32>` 类型
let mut optional = Some(0);

// 分析：当 `let` 将 `optional` 解构成 `Some(i)` 时，就
// 执行语句块（`{}`）。否则中断退出（`break`）。
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);
}
// ^ 使用的缩进更少，并且不用显式地处理失败情况。
}
// ^ `if let` 有额外可选的 `else`/`else if` 分句，
// 而 `while let` 没有。
}
``````