流程控制
表达式的形式
语句和表达式的区别:表达式总是返回一个值,而语句不会
1 + 1; // 这是表达式let a = 1; // 这是语句
Rust 是一个基于表达式的语言,它的大多数代码都有一个返回值,除了一下几种语法:
- 变量/模块/函数/结构体/枚举声明
- ……
在 Rust 中,条件与循环不是语句,而是表达式,可以有返回值
if 表达式,实现三元表达式
// a = cond ? 42 : 24;let cond = true;let a = if cond {42} else {24};
loop 表达式的 break 语句后面可跟返回值
let mut s = 0;let mut n = 10;let a = loop {if n < 0 {break s;}s += n;n -= 1;};println!("{:?}", a);
if_else 选择结构
如果使用if-else返回一个值,则所有分支必须返回相同的类型
let n = 0;let m = if n < 0 { 2.0 } else { 3.0 }; // 这里的; 不是if-else的,而是let赋值语句的println!("{:?}", m);
loop 循环
也有 break 和 continue
let mut sum = 0;let mut n = 1;loop {sum += n;n += 1;if n > 100 {break;}}println!("{}", sum);
break 关键字可以带上返回值,也就是 loop 的返回值,最大的用处是用于重试某个任务
while 循环
就是带循环条件的 loop
let mut sum = 0;let mut n = 1;while n <= 100 {sum += n;n += 1;}println!("{}", sum);
for-range 迭代
Rust 中的 for..in.. 语法可以用来遍历一个迭代器,和 Python 语法很相似
- 有多种方式可以创建迭代器,最常用的有:
a..b将创建一个 [a, b),步长为1的迭代器a..=b将创建一个 [a, b],步长为1的迭代器
for..in.. 语法第二个重要场景是遍历数组,需要先将数组转化为迭代器
可以通过
.iter()或者.iter_mut()实现fn main() {for i in 0..5 {println!("{}", i);}println!("======");for i in 11..=15 {println!("{}", i);}println!("======");let mut arr = [1, 2, 3];for i in arr.iter_mut() {*i *= 2;}for i in arr.iter() {println!("{}", i);}}
tips:当任务可以用while/loop/for-range完成,优先使用for-range
match 模式匹配
允许开发者将一个值与一系列模式进行比较,然后根据匹配的结果执行特定代码
- 与switch-case接近,但是更加强大
- match语法常常和enum一起使用,也经常用于匹配整型数据 ```rust enum Alphabet { A, B, }
fn main() { let letter = Alphabet::A;
match letter {Alphabet::A => {println!("it is A")}Alphabet::B => {println!("it is B")}}let n: u8 = 25;match n {25 => {println!("25")}_ => { // _ 为其他任意情况println!("{}", n)}}
}
<a name="G1WFD"></a>## if let 语法糖- 主要简化了 match 操作- 如果仅仅想当匹配发生时做某些操作,而忽略其他操作时,就可以用 if let 代替 match```rustenum Symbol {Char(char),Number,}fn main() {let letter = Symbol::Char('A');// letter 为 Symbol::Number 则什么都不会打印if let Symbol::Char(x) = letter {println!("{}", x)}}
while let 语法糖
- 比较少被使用到 ```rust enum Alphabet { A, B, }
fn main() { let mut letter = Alphabet::A;
while let Alphabet::A = letter { println!(“A”); letter = Alphabet::B; } }
<a name="ZB6Ua"></a>## 函数与方法<a name="heshh"></a>### 函数- 以fn开始,参数带类型注释,如果有返回值,则必须在 `->`之后指定返回类型```rustfn fib(n: u64) -> u64 {if n < 2 {return n;}return fib(n - 1) + fib(n - 2);}
方法
impl Point { // 构造方法,与普通方法没有区别,只是约定俗成叫 new fn new(x: u64, y: u64) -> Point { Point { x, y } }
fn get_x(&self) -> u64 {self.x}fn set_x(&mut self, x: u64) {self.x = x}
}
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()); }
<a name="yfwZo"></a>#<a name="pMKuA"></a># 函数和闭包- Rust 的闭包是一种匿名函数,它可以从上下文中捕获变量的值- 闭包使用`|| ->`语法定义,可以被保存在变量中```rustlet myclosures = |n: u32| -> u32 { n * 3 };println!("{}", myclosures(2));
move关键字:将环境中的值移到闭包内部,最常用的场景是:函数作为输入或者输出
- 数学中也叫做算子(运算符)或者泛函
将函数作为参数传递
```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)); }
<a name="ZKkMg"></a>## 将函数作为返回值```rusttype Method = fn(u32, u32) -> u32;fn add(a: u32, b: u32) -> u32 {a + b}fn sub(a: u32, b: u32) -> u32 {a - b}fn calc(method: &str) -> Method {match method {"add" => add,"sub" => sub,_ => unimplemented!(),}}fn main() {println!("{}", calc("add")(10, 1));}
发散函数
- 发散函数永远不会被返回,它们的返回值被标记为
!,这是一个空类型 - 最大用处是通过Rust的类型检查系统
- 基本不会用到 ```rust fn foo() -> ! { panic!(“this call never returns.”) }
fn main() { let a = if true { 10 } else { foo() }; println!(“{}”, a) } ```
