语句和表达式

Rust的函数体是由一系列语句组成,最后一个表达式来返回值,例如:

1
2
3
4
5
fn add_with_extra(x:i32, y:i32) -> i32{
let x = x+ 1;
let y = y + 5;
x + y;
}

语句会执行一些操作但是不会返回一个值,而表达式在球之后会返回一个值。

上面两行是语句,最后一行是表达式,返回值是 x+y 的结果。

rust中,基于语句和表达式的方式是非常重要的

语句

1
2
3
let a = 8;
let b:Vec<f64> = Vec::new();
let (a,c) = ("hi", false);

以上都是语句,他们完成一个具体的操作,但是没有返回值,因此是语句

由于let是语句,因此不能将let的返回值赋值给别的值

1
2
//error example
let b = (let a = 8);

表达式

表达式会进行求值,然后返回一个值,例如 5+6

表达式可以成为语句中的一部分,例如let y = 6 中, 6就是一个表达式。它在求值后返回一个值 6

调用一个函数是表达式,因为会返回一个值,调用宏也是表达式,用花括号包裹最终返回一个值的语句块也是表达式,总之,能返回值,就可以称为表达式。

1
2
3
4
5
6
7
8
fn main(){
let y = {
let x = 3;
x + 1
};

println!("The value of y is: {}", y);
}

上面使用一个语句块表达式给y赋值,该语句是表达式的原因是最后一行是表达式 x+1, 返回了x+1的值。

x+1不能以分号结尾,否则就会从表达式变成语句。表达式不能包含分号,这一点比较重要。如果加上分号就会变成语句,不会返回值,导致y的值是(),也就是单元类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

fn main() {
assert_eq! (ret_unit_type(), ());
}

fn ret_unit_type(){
let x = 1;

// if语句块也是一个表达式,因此可以用于赋值

let y = if x % 2 == 1 {
"odd"
} else {
"even"
};

//或者写成一行
let z = if x % 2 == 1 {"odd"} else {"even"};
}

函数

rust的函数在之前见过不少了,没有什么难度。

看看这个例子

1
2
3
fn add(i: i32, j : i32) -> i32{
i + j
}

该函数是如此的简单。

  • fn 关键字声明一个函数
  • add 函数名
  • (i: i32, j: i32) 函数参数列表,参数的类型必须显式标注
  • -> i32 函数返回值类型

函数要点

  • 函数名 和 变量名 使用蛇形命名法
  • 函数的位置可以随意放置,rust编译器会在编译期进行函数的解析
  • 每个函数参数都要标注类型

函数参数

1
2
3
4
5
6
7
8
fn main(){
another_function(5, 6.1);
}

fn another_function(x: i32, y: f32){
println!("The value of x is: {}", x);
println!("The value of y is: {}", y);
}

这里去掉任意一个参数的类型标注,都会报错,rust是静态类型语言,编译器必须在编译期知道所有变量的类型。

函数返回

上一节我们提到过,rust函数中,函数就是表达式,因此可以直接把函数的返回值赋给调用者

函数的返回值就是函数体最后一条表达式的返回值,当然我们也可以使用 return 提前返回。 下面的函数使用最后一个表达式来返回一个值

1
2
3
4
5
6
7
8
9

fn plus_five(x:i32) -> i32{
x + 5
}

fn main(){
let x = plus_five(5);
println!("The value of x is: {}", x);
}
  1. let x = plus_five(5); 我们使用一个函数的返回值来初始化x变量,因此侧面说明了rust中函数也是表达式
  2. x + 5 这条语句没有分号,因此是一个表达式,返回值就是 x+5 的结果。

在看一个

1
2
3
4
5
6
7
8
9
10
11
12
13

fn plus_or_minus(x:i32) -> i32{
if x > 5 {
return x - 5
}

x + 5
}

fn main(){
let x = plus_or_minus(5);
println!("The value of x is: {}", x);
}

rust中的特殊返回类型

无返回值()

  • 单元类型() 本质上就是一个空的元组类型,表示没有返回值的类型
1
2
3
4
5
6

use std::fmt::Debug;

fn report<T: Debug>(item: T) {
println!("{:?}", item);
}

上面这个函数就会隐式返回一个单元类型(),因为没有返回值。

1
2
3
fn clear(text:&mut String) -> () {
*text = String::from("");
}

上面这个函数显式返回一个单元类型()。

发散类型!

用 ! 作为类型的时候表示函数永不反悔,这种语法通常用于能够让程序崩溃的函数

1
2
3
fn dead_end() -> ! {
panic!("程序,你爆炸吧!");
}
1
2
3
4
5
fn forerver() -> ! {
loop {
println!("我永远不会返回");
};
}