流程控制
表达式的形式
语句和表达式的区别:表达式总是返回一个值,而语句不会
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
```rust
enum 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开始,参数带类型注释,如果有返回值,则必须在 `->`之后指定返回类型
```rust
fn 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 的闭包是一种匿名函数,它可以从上下文中捕获变量的值
- 闭包使用`|| ->`语法定义,可以被保存在变量中
```rust
let 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>
## 将函数作为返回值
```rust
type 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) } ```