理所当然地,Rust提供了条件、循环等控制流程。由于enum的特殊点(可以承载数据),Rust的条件结构为其有专门的设计,所以也在此简单介绍enum。
但寿元、所有权、引用借用等概念也影响enum的实际使用,故而会在Rust学习笔记/再叙enum和模式匹配再次讨论。
条件结构
if
表达式
if
后接一个 bool
类型的表达式(不需要括号),且 if
和 else
子句(均为表达式)均需要大括号。特殊地,如要书写 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
,但和其他语言相比多了对条件的完备性检查:必须匹配所有的可能性。另外,类似于 if
,match
也是表达式。
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支持三种循环结构 loop
、while
和 for
。
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)
则是我们说到的数据承载)。由于泛型和强类型两项特性,这一设定带来两个结论:
None
不能越过类型边界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評論。