Rust基础学习(二)——函数

paw5zx Lv4

语句(Statement)和表达式(Expression)

我们先了解一下语句(Statement)和表达式(Expression),这对后面学习函数有所帮助:

  • 语句执行某些操作且不返回值。
  • 表达式求出并返回一个结果值。

语句

使用let关键字创建变量并赋值是一个语句

1
2
3
4

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

语句不返回值,因此你不能将一个let语句赋值给另一个变量:

1
2
// let y = 6不返回值,因此x没有任何值可以绑定
let x = (let y = 6);

函数定义也是语句。(调用函数不是语句,而是表达式)

表达式

表达式求出并返回一个值,考虑一个数学运算,例如5 + 6,求出值11并返回,因此它是表达式。

表达式可以是语句的一部分:let y = 6中的6就是一个表达式。此外,调用函数是表达式。调用宏是表达式。用花括号创建的新作用域块也是表达式,叫块表达式(Block Expression):

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

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

上述代码将块表达式计算出的值绑定到y,块表达式为:

1
2
3
4
{
let x = 3;
x + 1
}

注意,x + 1这行的结尾没有分号。上述语句块返回了x + 1的值(块表达式的返回值是块中最后一个表达式的值)。如果最后一个表达式后面有分号,那么整个块会返回一个单元类型()

Paw5zx注:

一旦你在表达式的结尾添加了分号,它就变成了一个语句,将不会返回任何值。

函数

  • 使用fn关键字声明新函数
  • 函数名和变量名使用蛇形命名法(snake case):所有字母都是小写,单词之间用下划线分隔
  • 函数参数需要标注类型
  • 函数返回值类型须在->后显式声明
  • 函数可以定义在调用者可见范围内的任意位置,这个范围指的是:
    • 同一个文件(模块):在同一个文件中,可以在文件的任何位置定义函数,只要它们位于相同的模块或命名空间中
    • 父模块或子模块:如果一个模块想要调用另一个模块中定义的函数,那么被调用的函数需要被标记为pub
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      fn main()
      {
      println!("Hello, world!");

      another_function();
      }
      // 定义在调用者之后
      fn another_function()
      {
      println!("Another function.");
      }
  • 函数体由一系列语句组成,可选地以一个表达式结尾

函数参数

Rust是静态类型语言,参数是函数签名的一部分,因此需要为每个函数参数都标识出它的具体类型

我们重写下another_function,为它添加一个参数:

1
2
3
4
5
6
7
8
9
10
11
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);
}

这个版本的another_function有两个参数,其中xi32类型,yf32类型。注意,去掉x或者y的任何一个的类型,都会报错。

Paw5zx注:

在函数签名中,必须声明每个参数的类型。这是Rust设计中的一个刻意决策:要求在函数定义中注明类型(type annotations),这意味着编译器几乎不需要通过你在代码的其他地方使用类型注解来判断你指的是哪种类型。这样做可以让代码更清晰,并减少类型错误。

函数返回

函数是表达式,可以将值返回给调用者。在函数声明中,我们不为返回值命名,但必须在->后声明返回值类型。

在Rust中,函数的返回值与函数体中最后一个表达式的值相同。

1
2
3
4
5
6
7
8
9
10
11
fn five() -> i32
{
5
}

fn main()
{
let x = five();

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

当然,也可以使用return关键字指定一个值,提前返回:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fn main()
{
let x = plus_or_minus(6);

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

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

x + 5
}

但是要注意,此例中不要在函数体内最后一个表达式后加分号,会编译报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 此段代码编译错误
fn main()
{
let x = plus_or_minus(6);

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

fn plus_or_minus(x:i32) -> i32
{
if x > 5
{
// return后有没有分号在语法上都是可行的
return x - 5;
}

// 此处报错,因为定义要求返回值类型为i32,但是实际返回单元类型(),与函数定义矛盾
x + 5;
}

参考文章

1.《Rust语言圣经》
2.《The Rust Programming Language》

  • 标题: Rust基础学习(二)——函数
  • 作者: paw5zx
  • 创建于 : 2025-01-23 14:43:22
  • 更新于 : 2025-02-09 13:52:14
  • 链接: https://paw5zx.github.io/rust-common-concepts-2/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论