声明函数
在 Rust 中,使用 fn
关键字来声明一个函数,例如程序的入口函数: main
函数。
Rust 代码中的函数和变量名使用下划线命名法(snake case,直译为蛇形命名法)规范风格。在下划线命名法中,所有字母都是小写并使用下划线分隔单词。
fn main() {
println!("Hello, world!");
another_function();
}
fn another_function() {
println!("Another function.");
}
函数参数
函数也可以被定义为拥有参数(parameter),参数是特殊变量,是函数签名的一部分。当函数拥有参数(形参)时,可以为这些参数提供具体的值(实参)。技术上讲,这些具体值被称为实参(argument),但是在日常交流中,人们倾向于不区分使用 parameter 和 argument 来表示函数定义中的变量或调用函数时传入的具体值。
修改上面的代码,在声明的 another_function
函数中添加一个参数 x
,并在调用函数时将实参 5
传给这个函数。
fn main() {
another_function(5);
}
fn another_function(x: i32) {
println!("The value of x is: {}", x);
}
注意: 在函数签名中,必须声明每个参数的类型。当一个函数有多个参数时,使用逗号分隔。
fn main() {
print_labeled_measurement(5, 'h');
}
fn print_labeled_measurement(value: i32, unit_label: char) {
println!("The measurement is: {}{}", value, unit_label);
}
语句和表达式
函数体由一系列语句组成,也可选择以表达式结尾。因为 Rust 是一门基于表达式(expression-based)的语言,所以这是一个需要理解的重要区别。其他语言没有这样的区别,所以让我们看看语句和表达式分别是什么,以及它们的区别如何影响函数体。
语句(statement)是执行一些操作但不返回值的指令。表达式(expression)计算并产生一个值。让我们看一些例子:
语句
使用 let
关键字创建变量并绑定一个值是一个语句,函数定义也是语句。语句不返回值。因此,不能把 let
语句赋值给另一个变量。例如 let x = (let y = 6);
即为一个错误的示范。而在其他一些语言,例如 C 语言中,x = y = 6
的写法是可行的,因为 C 语言中的赋值语句会返回所赋的值。
表达式
表达式会计算出一个值,并且用 Rust 编写的大部分代码都由表达式组成。考虑一个数学运算,比如 5 + 6
,这是一个表达式并计算出值 11
。表达式可以是语句的一部分:语句 let y = 6;
中的 6
是一个表达式,它计算出的值是 6
。函数调用是一个表达式。宏调用是一个表达式。我们用来创建新作用域的大括号(代码块) {}
也是一个表达式,例如:
fn main() {
let y = {
let x = 3;
x + 1
};
println!("The value of y is: {}", y);
}
其中的表达式:
{
let x = 3;
x + 1
}
是一个代码块,在这个例子中计算结果是 4
。这个值作为 let
语句的一部分被绑定到 y
上。注意,x + 1
行的末尾没有分号,这与你目前见过的大部分代码行不同。表达式的结尾没有分号。如果在表达式的末尾加上分号,那么它就转换为语句,而语句不会返回值。
函数返回值
函数可以向调用它的代码返回值。我们并不对返回值命名,但要在箭头(->
)后声明它的类型。在 Rust 中,函数的返回值等同于函数体最后一个表达式的值。使用 return
关键字和指定值,可以从函数中提前返回;但大部分函数隐式返回最后一个表达式。这是一个有返回值函数的例子:
fn five() -> i32 {
5
}
fn main() {
let x = five();
println!("The value of x is: {}", x);
}
five
函数没有参数并定义了返回值类型,不过函数体只有单单一个 5
也没有分号,因为这是一个表达式,正是我们想要返回的值。
下面再来看一个带参数并返回值的函数的例子:
fn main() {
let x = plus_one(5);
println!("The value of x is: {}", x);
}
fn plus_one(x: i32) -> i32 {
x + 1
}
运行代码会打印出 The value of x is: 6
。但如果在包含 x + 1
的行尾加上一个分号,把它从表达式变成语句,我们将得到一个错误: error[E0308]: mismatched types
。
这是因为如果在 x + 1
后面加上分号,该表达式将变成语句,而语句不返回值,因此函数返回由单元类型 ()
表示,表示不返回值,与声明的 i32
类型不匹配。