Rust学习笔记/基本控制流程与enum

renyuneyun 2018年08月07日(周二) 1 mins

理所当然地,Rust提供了条件、循环等控制流程。由于enum的特殊点(可以承载数据),Rust的条件结构为其有专门的设计,所以也在此简单介绍enum。

但寿元、所有权、引用借用等概念也影响enum的实际使用,故而会在Rust学习笔记/再叙enum和模式匹配再次讨论。

条件结构

if 表达式

if 后接一个 bool 类型的表达式(不需要括号),且 ifelse 子句(均为表达式)均需要大括号。特殊地,如要书写 else-if ,则 else if 合并为一个表达式。

...
let m = if a < 5 {
  println!("a小于5");
  4
} else if a < 8 {
  println!("a小于8");
  7
} else {
  10
}
println!("m={}", m);

注意 if 各子句(表达式)的返回值应当是相同的类型,否则会造成编译错误(类型错误)。

另外, if 表达式还支持与enum联合使用的模式匹配,使用 if let 语法,见下文enum部分。

模式匹配(match)

Rust的 match 基本就是其他语言中的 switch,但和其他语言相比多了对条件的完备性检查:必须匹配所有的可能性。另外,类似于 ifmatch 也是表达式。

let x = 5;

let number = match x {
    1 => "one",
    2 => "two",
    3 => "three",
    4 => "four",
    5 => "five",
    _ => "anything else",
};

上面代码展示了match的基本语法,其中_代表「任何」(也就是其他语言中的default)。

理论上来说,同一枝匹配的「模式」也可以是多值,比如如下的例子:

match x {
    1 | 2 => "one or two",
    3 ..= 9 => "three to nine",
    _ => "anything else",
};

注意这里的范围是用「范围模式」而非「 范围表达式」写就的。官方文档的内容预示着还有更高级的形式,有兴趣的可以去翻阅文档。

当涉及enum后,match则起到更大的作用(见下文)。

循环结构

Rust支持三种循环结构 loopwhilefor

loop

loop 产生一个无限循环,等价于C中的 while (1)

fn main() {
    loop {
        println!("again!");
    }
}

来自 官方教程控制流程一节

while

while 就是正常的 while 结构,不进行赘述。

if 一样,其条件表达式也不需要括号;同 if 一样,其也支持 while let 语法进行模式匹配(见下面enum部分)。

for

for 就是 for each。同Python中的写法类似,Rust中也需要 for ... in ...

fn main() {
    let a = [10, 20, 30, 40, 50];

    for element in a.iter() {
        println!("the value is: {}", element);
    }
}
fn main() {
    for number in (1..4).rev() {
        println!("{}!", number);
    }
    println!("LIFTOFF!!!");
}

同样来自 官方教程控制流程一节

enum

Rust的enum可以简单承载数据,这使得它承担了一些很有意义的其他功能。

比如说,Rust中没有null(不是改名这种文字游戏),取而代之的则是一个叫做Option<T>的enum,其有效取值分别是Some(T)None(和你想得一样,这里的<T>是泛型参数,而(T)则是我们说到的数据承载)。由于泛型和强类型两项特性,这一设定带来两个结论:

  1. None不能越过类型边界
  2. Some(T)None必须分别处理,否则编译无法通过

于是,对Java等语言中普遍存在的空指针问题,Rust程序员完全不需要担心:编译时就需要确认数据是否存在,运行时一定不会出现空指针。

特殊设计的 if let 等结构便是配合这类机制的良方,方便写出简短的代码:

let some_value = Some(3);

if let None = some_value {
    println!("some_value is None")
}

if let Some(x) = some_value {
    println!("{}", x);
}


let some_value2 = Some("test");

match some_value2 {
    Some(s) => println!("{}", s),
    None => println!("None!"),
}

可以看到,这里的控制流程的判定条件是该赋值是否成功,并且变量x被自动解包赋值(3,而非Some(3))。 另外,这里的match并没有使用_,因为Rust编译器知道some_value2是一个Option类型(更具体的,Option<&'static str>类型)的值,其可能取值只有两种。


您可以在Hypothesis上的該群組內進行評論,或使用下面的Disqus評論。