流程控制

表达式的形式

  • 语句和表达式的区别:表达式总是返回一个值,而语句不会

    1. 1 + 1; // 这是表达式
    2. let a = 1; // 这是语句
  • Rust 是一个基于表达式的语言,它的大多数代码都有一个返回值,除了一下几种语法:

    • 变量/模块/函数/结构体/枚举声明
    • ……
  • 在 Rust 中,条件与循环不是语句,而是表达式,可以有返回值

    if 表达式,实现三元表达式

    1. // a = cond ? 42 : 24;
    2. let cond = true;
    3. let a = if cond {
    4. 42
    5. } else {
    6. 24
    7. };

    loop 表达式的 break 语句后面可跟返回值

    1. let mut s = 0;
    2. let mut n = 10;
    3. let a = loop {
    4. if n < 0 {
    5. break s;
    6. }
    7. s += n;
    8. n -= 1;
    9. };
    10. println!("{:?}", a);

    if_else 选择结构

  • 如果使用if-else返回一个值,则所有分支必须返回相同的类型

    1. let n = 0;
    2. let m = if n < 0 { 2.0 } else { 3.0 }; // 这里的; 不是if-else的,而是let赋值语句的
    3. println!("{:?}", m);

    loop 循环

  • 也有 break 和 continue

    1. let mut sum = 0;
    2. let mut n = 1;
    3. loop {
    4. sum += n;
    5. n += 1;
    6. if n > 100 {
    7. break;
    8. }
    9. }
    10. println!("{}", sum);
  • break 关键字可以带上返回值,也就是 loop 的返回值,最大的用处是用于重试某个任务

    while 循环

  • 就是带循环条件的 loop

    1. let mut sum = 0;
    2. let mut n = 1;
    3. while n <= 100 {
    4. sum += n;
    5. n += 1;
    6. }
    7. println!("{}", sum);

    for-range 迭代

  • Rust 中的 for..in.. 语法可以用来遍历一个迭代器,和 Python 语法很相似

  • 有多种方式可以创建迭代器,最常用的有:
    • a..b将创建一个 [a, b),步长为1的迭代器
    • a..=b将创建一个 [a, b],步长为1的迭代器
  • for..in.. 语法第二个重要场景是遍历数组,需要先将数组转化为迭代器

    • 可以通过.iter()或者.iter_mut()实现

      1. fn main() {
      2. for i in 0..5 {
      3. println!("{}", i);
      4. }
      5. println!("======");
      6. for i in 11..=15 {
      7. println!("{}", i);
      8. }
      9. println!("======");
      10. let mut arr = [1, 2, 3];
      11. for i in arr.iter_mut() {
      12. *i *= 2;
      13. }
      14. for i in arr.iter() {
      15. println!("{}", i);
      16. }
      17. }
  • tips:当任务可以用while/loop/for-range完成,优先使用for-range

    match 模式匹配

  • 允许开发者将一个值与一系列模式进行比较,然后根据匹配的结果执行特定代码

  • 与switch-case接近,但是更加强大
  • match语法常常和enum一起使用,也经常用于匹配整型数据 ```rust enum Alphabet { A, B, }

fn main() { let letter = Alphabet::A;

  1. match letter {
  2. Alphabet::A => {
  3. println!("it is A")
  4. }
  5. Alphabet::B => {
  6. println!("it is B")
  7. }
  8. }
  9. let n: u8 = 25;
  10. match n {
  11. 25 => {
  12. println!("25")
  13. }
  14. _ => { // _ 为其他任意情况
  15. println!("{}", n)
  16. }
  17. }

}

  1. <a name="G1WFD"></a>
  2. ## if let 语法糖
  3. - 主要简化了 match 操作
  4. - 如果仅仅想当匹配发生时做某些操作,而忽略其他操作时,就可以用 if let 代替 match
  5. ```rust
  6. enum Symbol {
  7. Char(char),
  8. Number,
  9. }
  10. fn main() {
  11. let letter = Symbol::Char('A');
  12. // letter 为 Symbol::Number 则什么都不会打印
  13. if let Symbol::Char(x) = letter {
  14. println!("{}", x)
  15. }
  16. }

while let 语法糖

  • 比较少被使用到 ```rust enum Alphabet { A, B, }

fn main() { let mut letter = Alphabet::A;

while let Alphabet::A = letter { println!(“A”); letter = Alphabet::B; } }

  1. <a name="ZB6Ua"></a>
  2. ## 函数与方法
  3. <a name="heshh"></a>
  4. ### 函数
  5. - 以fn开始,参数带类型注释,如果有返回值,则必须在 `->`之后指定返回类型
  6. ```rust
  7. fn fib(n: u64) -> u64 {
  8. if n < 2 {
  9. return n;
  10. }
  11. return fib(n - 1) + fib(n - 2);
  12. }

方法

  • 是附加到对象上的函数 ```rust

    [derive(Debug)]

    struct Point { x: u64, y: u64, }

impl Point { // 构造方法,与普通方法没有区别,只是约定俗成叫 new fn new(x: u64, y: u64) -> Point { Point { x, y } }

  1. fn get_x(&self) -> u64 {
  2. self.x
  3. }
  4. fn set_x(&mut self, x: u64) {
  5. self.x = x
  6. }

}

fn main() { let mut point = Point::new(20, 20); println!(“{:?}”, point); println!(“x = {}”, point.get_x()); // 调用实例的方法使用 . point.set_x(100); println!(“x = {}”, point.get_x()); }

  1. <a name="yfwZo"></a>
  2. #
  3. <a name="pMKuA"></a>
  4. # 函数和闭包
  5. - Rust 的闭包是一种匿名函数,它可以从上下文中捕获变量的值
  6. - 闭包使用`|| ->`语法定义,可以被保存在变量中
  7. ```rust
  8. let myclosures = |n: u32| -> u32 { n * 3 };
  9. println!("{}", myclosures(2));
  • move关键字:将环境中的值移到闭包内部,最常用的场景是:

    • 将主线程中的一个变量传递到子线程
      1. let message = "hello";
      2. thread::spawn(move || println!("{}", message)).join();

      高阶函数

  • 函数作为输入或者输出

  • 数学中也叫做算子(运算符)或者泛函

    将函数作为参数传递

    ```rust type Method = fn(u32, u32) -> u32;

fn calc(method: Method, a: u32, b: u32) -> u32 { method(a, b) }

fn add(a: u32, b: u32) -> u32 { a + b }

fn sub(a: u32, b: u32) -> u32 { a - b }

fn main() { println!(“{}”, calc(add, 10, 1)); println!(“{}”, calc(sub, 10, 1)); }

  1. <a name="ZKkMg"></a>
  2. ## 将函数作为返回值
  3. ```rust
  4. type Method = fn(u32, u32) -> u32;
  5. fn add(a: u32, b: u32) -> u32 {
  6. a + b
  7. }
  8. fn sub(a: u32, b: u32) -> u32 {
  9. a - b
  10. }
  11. fn calc(method: &str) -> Method {
  12. match method {
  13. "add" => add,
  14. "sub" => sub,
  15. _ => unimplemented!(),
  16. }
  17. }
  18. fn main() {
  19. println!("{}", calc("add")(10, 1));
  20. }

发散函数

  • 发散函数永远不会被返回,它们的返回值被标记为!,这是一个空类型
  • 最大用处是通过Rust的类型检查系统
  • 基本不会用到 ```rust fn foo() -> ! { panic!(“this call never returns.”) }

fn main() { let a = if true { 10 } else { foo() }; println!(“{}”, a) } ```