Skip to main content
2 函数与控制流

2 函数与控制流

•1 min•103 words

函数

函数通过fn关键字定义

函数的定义,关键字是fn并且另外的特征是函数名后跟上()这是函数的参数列表待的地方。

Warning
更多函数知识

高级知识,闭包,嵌套函数等,后面可以学。
.
想要运行时读取以及更新状态,可以使用闭包,但是闭包不能调用自己。最好的方法是使用fn并将状态通过引用参数传入fn函数。

Rust 不关心函数定义所在的位置,只要函数被调用时出现在调用之处可见的作用域内就行。

两阶段编译

C 语言的编译方式:单趟扫描(One-pass),如果调用之前没看到定义就认为未定义。
Rust 是 两阶段编译(Two-pass),会先进行全文扫描,收集所有函数、结构体、模块名字,然后进行编译,这意味着rust的眼睛不瞎,无论定义在之前还是之后,只要在一个作用域,都能看到。

rust必须让我们在定义函数的时候,给形参加类型。因为这是静态类型语言。

Summary
cargo rustc --release -- --emit asm # 生成汇编文件在target/release/deps/<name>.s

rust的赋值语句并不是表达式,因此,在那些语言中你可以写 x = y = 6,让 x 和 y 都得到值 6;但 Rust 不是这样。

Rust中有更多的表达式

函数调用是一个表达式。用大括号创建的一个新的块作用域也是一个表达式。更多的语句块都是表达式。

Todo
let y = { 
  let x = 3; 
  x + 1  // 注意这里不要加分号,否则会变成语句
};
Summary
fn five() -> i32 { 
  5 // 或者 result 5;
}

可以使用 return 关键字并指定一个值,从函数中提前返回;不过大多数函数都会隐式返回最后一个表达式的值。

注释

没有多行注释

rust只支持单行注释//,或者 文档注释三条斜杠 ///以及//!
没有/**/这种

控制流

if 表达式

if else if

与c语言不同的是 if后面直接用空格分隔bool表达式即可,不需要用括号。
rust不会隐式转换,注意这里必须是bool表达式哦。

因为if接的也是作用域块,所以if表达式也是表达式,我们可以使用这样的语法:

let x = if 1>2 { 1 } else { 2 };

但是需要注意,if后面的块与else后面的块返回的类型一定要相同,否则编译器会报错。

match 替代if else if 嵌套

if else if嵌套就是一个多分支的条件树,如果写太长了非常的不直观。rust提供了match语法,类似switch。后面介绍。

循环 表达式

Rust提供了三种循环,loop,while和for

loop 无限循环

标记一个代码块{},然后永远的循环执行。可以使用ctrl-c输入终止,或者break跳出循环,或者continue直接开始下一个循环。

循环中返回值

因为循环声明的也是一个代码块{},所以循环也是表达式。我们可以使用break来接要返回的表达式break x*2;而放在代码块最后的表达式因为无法终结循环,所以这种返回值写法没有能成功的场景。

Summary
let y:i32 = 'tag_name_1: loop {
  println!("loop1");
  let mut x = 1;
  loop {
  	x += 1;
  	if x > 10 {
  		break 'tag_name_1 x;
  	}
  }
  break 0; // 编译器会提示永远不可达
};

标签的语法是'<tag_name>: 前单引号,中间字符串,后面引号

break的时候,先写标签,后写返回表达式。

while循环

因为while循环的模式过于常见,所以rust也支持while循环。while <bool表达式> { 代码块 }

Summary
for x in 1..5 { 
// 循环体 
}
// ------- 本质展开 ----------
let mut iter = (1..5).into_iter();
// 关键点:x 绑定在整个循环外面
loop {
   match iter.next() {
       Some(x) => {
           // 循环体
       }
       None => break,
   }
}

for 循环的安全性和简洁性,使它成为 Rust 中最常用的循环结构。