跳转至

Control Flows

本节介绍Rust中的函数和控制流语句。

函数与函数指针

Rust中,用关键字fn声明函数,函数的格式为:

fn <function name>([<parameter name>: <parameter type>, ...]) -> [<return type>] {
    <function body>
}

其中,函数必须指明所有参数的类型。如果没有指明函数的返回类型,则默认为(),即空元组。函数可以通过return关键字返回值,也可以通过最后一行的表达式返回值。任何情况下,如果通过表达式返回值,则不能加分号;

Download source code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
fn add(a: i32, b: i32) -> i32 {
    a + b // Return by expression
}
fn sub(a: i32, b: i32) -> i32 {
    return a - b; // Return by return keyword
}

fn main() {
    let (a, b) = (2, 1);
    println!("{} + {} = {}", a, b, add(a, b));
    println!("{} - {} = {}", a, b, sub(a, b));
}

函数指针的类型为fn(<parameter type>, ...) -> <return type>,将函数赋值给函数指针时,参数列表和返回值类型必须全部匹配。

在函数内部也可以声明函数,称为lambda函数,声明方式为

let <function name> = |[<parameter name>: <parameter type>, ...]| -> [<return type>] {
    <function body>
}

其中:

  1. 参数列表可以省略类型。

    let add = |a, b| { return a + b; };
    
  2. 如果函数体只有一行,可以省略{},此时不能加返回值类型。

    let add = |a, b| a + b;
    
  3. 可以在声明的时候直接调用,此时不能省略{}和返回值类型。

    let result = |a, b| -> i32 { a + b }(1, 2); // result = 3
    

Download source code

1
2
3
4
5
6
fn main() {
    let (a, b) = (2, 1);
    let add = |a, b| a + b;
    println!("{} + {} = {}", a, b, add(a, b));
    println!("{} - {} = {}", a, b, |a, b| -> i32 { return a - b; }(a, b));
}

if语句

Rust中if语句的格式与C/C++相似,但是条件表达式不需要加括号。

if <condition> {
    <expression>
} [ else if <condition> {
    <expression>
} ] [ else {
    <expression>
} ]

if语句也可以用在表达式中,此时每个分支块的最后一行作为该分支的返回值。此时每个分支的返回值类型必须相同。

Download source code

1
2
3
4
5
6
7
8
9
fn main() {
    let (a, b) = (5, 3);
    println!("max({}, {}) = {}", a, b, if a > b { a } else { b });
    if a < b {
        println!("min({}, {}) = {}", a, b, a);
    } else {
        println!("min({}, {}) = {}", a, b, b);
    }
}

match语句

match语句用于对变量的值进行模式匹配,格式为:

match <variable> {
    <pattern> => <expression>,
    ...
    _ => <expression>
}

其中,<pattern>可以是

  1. 单个数值,如5 => "five"
  2. 范围,如1 ..= 5 => "one to five"
  3. |分隔的多个模式,如1 | 2 | 3 => "one to three"
  4. 模板实例,如Some(x) => Some(x + 1)
  5. _,表示匹配所有情况。
  6. 如果被匹配的变量是元组,则元组的每个元素都可以是上述模式。
  7. 条件语句,如x if x > 5 => "greater than five",此时元组是一个整体参与条件语句,如(x, y) if x > 5 && y > 5 => "both greater than five"

<expression>可以是返回值,也可以是代码块,此时代码块的最后一行作为返回值。

注意match的分支必须包括所有可能的情况,否则会报错。

Download source code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
fn main() {
    let marks_paper_a: u8 = 25;
    let marks_paper_b: u8 = 30;

    let output = match (marks_paper_a, marks_paper_b) {
        (50, 50) => "Full marks for both papers",
        (50, _) => "Full marks for paper A",
        (_, 50) => "Full marks for paper B",
        (x, y) if x > 25 && y > 25 => "Good",
        (_, _) => "Work hard"
    };

    println!("{}", output); // Work hard
}

if let语句

match类似,if let语句用于匹配单个模式,格式为:

if let <pattern> = <variable> {
    <expression>
}

let <pattern> = <variable>可以看成一个条件(但实际并不是),如果能匹配则将<variable>的值按照<pattern>进行绑定,并返回true,因此也会有while let等其他语句。

loop语句

loop语句用于无限循环。

  1. 可以用continue跳转到下一次循环,或break跳出循环。
  2. loop可以用break <expression>返回值,此时所有break的返回值类型必须相同。
  3. 每个循环可以用'<label>: loop标记,在breakcontinue时可以指定跳出/跳过的循环。

Download source code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
fn main() {
    let mut b1 = 1;

    let (c1, c2) = 'outer_loop: loop {
      let mut b2 = 1;

      'inner_loop: loop {
        println!("Current Value : [{}][{}]", b1, b2);

        if b1 == 2 && b2 == 2 {
            break 'outer_loop (b1, b2); // Leave outer_loop with return value
        } else if b2 == 5 {
            break; // Leave inner_loop by default
        }

        b2 += 1;
      }

      b1 += 1;
    };
    println!("b1 = {}, b2 = {}", c1, c2);
}

while语句

while语句用于是有条件的循环,while语句不能返回值,其他与loop语句相同。

while <condition> {
    <expression>
}

for语句

for语句用于遍历迭代器,格式为:

for <variable> in <iterator> {
    <expression>
}

其中,<iterator>可以是

  1. start .. end,表示从startend - 1的整数范围。
  2. start ..= end,表示从startend的整数范围。
  3. 由方法<iterable>.iter()返回的迭代器,如[1, 2, 3].iter()

for循环也可以添加标签。

Download source code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
fn main() {
    let group : [&str; 4] = ["Mark", "Larry", "Bill", "Steve"];

    for n in 0..group.len() { // group.len() = 4 -> 0..4 👎 check group.len()on each iteration
    println!("Current Person : {}", group[n]);
    }

    for person in group.iter() { // 👍 group.iter() turn the array into a simple iterator
    println!("Current Person : {}", person);
    }
}

严格意义上for语句不能直接遍历容器对象,需要用iter()方法返回迭代器。但for会尝试隐式调用,因此下面的代码也能正常执行。

fn main() {
    let a = [1, 2, 3];
    for i in a {
        println!("{}", i);
    }
}

评论