功能
函数在 Rust 代码中很普遍。您已经见过最
语言中的重要函数:main
函数,即入口
许多程序的点。您还看到了fn
关键字,它允许您
声明新函数。
Rust 代码使用蛇形大小写作为函数和变量的常规样式 names,其中所有字母均为小写,并为单独的单词添加下划线。 下面是一个包含示例函数定义的程序:
文件名: src/main.rs
fn main() { println!("Hello, world!"); another_function(); } fn another_function() { println!("Another function."); }
我们在 Rust 中通过输入fn
后跟函数名称和
一组括号。大括号告诉编译器函数
身体开始和结束。
我们可以通过输入其名称后跟集合来调用我们定义的任何函数
的括号。因为another_function
在程序中定义,则可以是
从main
功能。请注意,我们定义了another_function
在main
function 在源代码中;我们之前可以定义它
也。Rust 不在乎你在哪里定义你的函数,只关心它们在哪里
在调用方可以看到的作用域中的某个位置定义。
让我们启动一个名为 functions 的新二进制项目来探索函数
进一步。将another_function
example 并运行它。你
应看到以下输出:
$ cargo run
Compiling functions v0.1.0 (file:///projects/functions)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.28s
Running `target/debug/functions`
Hello, world!
Another function.
这些行按照它们在main
功能。
首先打印 “Hello, world!” 消息,然后another_function
称为
它的信息被打印出来。
参数
我们可以定义函数来具有参数,这些参数是特殊的变量 是函数签名的一部分。当函数具有参数时,您可以 为其提供这些参数的具体值。从技术上讲,混凝土 值称为参数,但在随意的对话中,人们倾向于使用 words 参数和参数可互换用于任一变量 在函数的定义中,或者调用时传入的具体值 功能。
在这个版本的another_function
我们添加一个参数:
文件名: src/main.rs
fn main() { another_function(5); } fn another_function(x: i32) { println!("The value of x is: {x}"); }
尝试运行此程序;您应该得到以下输出:
$ cargo run
Compiling functions v0.1.0 (file:///projects/functions)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.21s
Running `target/debug/functions`
The value of x is: 5
的声明another_function
有一个名为x
.的类型x
指定为i32
.当我们通过5
in 到another_function
这println!
宏 Put5
其中,包含x
是
在 format string.
在函数签名中,必须声明每个参数的类型。这是 Rust 设计中的一个深思熟虑的决定:在函数中要求类型注释 定义意味着编译器几乎不需要您在 用于弄清楚您的类型的代码。编译器还能够给出 如果它知道函数需要什么类型,则更有用的错误消息。
定义多个参数时,使用 逗号,如下所示:
文件名: src/main.rs
fn main() { print_labeled_measurement(5, 'h'); } fn print_labeled_measurement(value: i32, unit_label: char) { println!("The measurement is: {value}{unit_label}"); }
此示例创建一个名为print_labeled_measurement
with two
参数。第一个参数名为value
,并且是一个i32
.第二个是
叫unit_label
和 is 类型char
.然后,该函数打印包含
这两个value
和unit_label
.
让我们尝试运行这段代码。将函数项目的 src/main.rs 文件中的当前程序替换为前面的示例,并使用cargo run
:
$ cargo run
Compiling functions v0.1.0 (file:///projects/functions)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.31s
Running `target/debug/functions`
The measurement is: 5h
因为我们用5
作为value
和'h'
如
的值unit_label
,则程序输出将包含这些值。
语句和表达式
函数体由一系列语句组成,可选地以 表达。到目前为止,我们介绍的函数尚未包含结尾 expression,但您已将 expression 视为语句的一部分。因为 Rust 是一种基于表达式的语言,这是 理解。其他语言没有相同的区别,所以让我们看看 什么是语句和表达式以及它们的差异如何影响身体 的功能。
- 语句是执行某些作但不返回的指令 一个值。
- 表达式的计算结果为结果值。让我们看一些例子。
我们实际上已经使用了 statements 和 expressions。创建变量并
使用let
keyword 是一个语句。在示例 3-1 中,let y = 6;
是一个声明。
fn main() { let y = 6; }
main
包含一个语句的函数声明函数定义也是语句;前面的整个示例是一个 声明本身。(正如我们将在下面看到的,调用函数不是 声明。
语句不返回值。因此,您不能分配let
陈述
添加到另一个变量中,就像下面的代码尝试执行的作一样;您将收到一个错误:
文件名: src/main.rs
fn main() {
let x = (let y = 6);
}
当您运行此程序时,您将得到的错误如下所示:
$ cargo run
Compiling functions v0.1.0 (file:///projects/functions)
error: expected expression, found `let` statement
--> src/main.rs:2:14
|
2 | let x = (let y = 6);
| ^^^
|
= note: only supported directly in conditions of `if` and `while` expressions
warning: unnecessary parentheses around assigned value
--> src/main.rs:2:13
|
2 | let x = (let y = 6);
| ^ ^
|
= note: `#[warn(unused_parens)]` on by default
help: remove these parentheses
|
2 - let x = (let y = 6);
2 + let x = let y = 6;
|
warning: `functions` (bin "functions") generated 1 warning
error: could not compile `functions` (bin "functions") due to 1 previous error; 1 warning emitted
这let y = 6
statement 不返回值,因此没有x
绑定到。这与其他语言中发生的情况不同,例如
C 和 Ruby,其中赋值返回赋值。在那些
languages 中,您可以编写x = y = 6
并且两者兼而有之x
和y
具有6
;在 Rust 中不是这种情况。
表达式的计算结果为一个值,并构成了其余代码的大部分
您将使用 Rust 编写。考虑一个数学运算,例如5 + 6
,它是一个
表达式,该表达式的计算结果为值11
.表达式可以是
statements:在示例 3-1 中,6
在声明中let y = 6;
是一个
表达式,该表达式的计算结果为值6
.调用函数是一个
表达。调用宏是一个表达式。使用
大括号是一个表达式,例如:
文件名: src/main.rs
fn main() { let y = { let x = 3; x + 1 }; println!("The value of y is: {y}"); }
此表达式:
{
let x = 3;
x + 1
}
是一个块,在本例中,其计算结果为4
.该值绑定到y
作为let
陈述。请注意,x + 1
行没有
分号,这与你目前看到的大多数行不同。
表达式不包括结束分号。如果在末尾添加分号
表达式中,将其转换为语句,然后它不会返回
价值。在探索函数返回值和表达式时,请记住这一点
下一个。
具有返回值的函数
函数可以将值返回给调用它们的代码。我们不命名 return
值,但我们必须在箭头 () 后声明它们的类型。在 Rust 中,
函数的返回值与最终的
expression 在函数体的块中。您可以从
函数。->
return
keyword 并指定一个值,但大多数
函数隐式返回最后一个表达式。下面是一个
函数返回一个值:
文件名: src/main.rs
fn five() -> i32 { 5 } fn main() { let x = five(); println!("The value of x is: {x}"); }
没有函数调用、宏,甚至没有let
语句中的five
function - 仅数字5
靠它自己。这是一个完全有效的函数
锈。请注意,该函数的返回类型也被指定,如-> i32
.尝试
运行此代码;输出应如下所示:
$ cargo run
Compiling functions v0.1.0 (file:///projects/functions)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.30s
Running `target/debug/functions`
The value of x is: 5
这5
在five
是函数的返回值,这就是为什么返回类型
是i32
.让我们更详细地研究一下。有两个重要的部分:
首先,线let x = five();
显示我们正在使用
函数来初始化变量。由于函数five
返回5
,
该行与以下内容相同:
#![allow(unused)] fn main() { let x = 5; }
其次,five
function 没有参数,并定义了
返回值,但函数体是孤独的5
没有分号
因为它是我们要返回其值的表达式。
让我们看另一个例子:
文件名: src/main.rs
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
,将其从
expression 添加到语句中,我们将收到一个错误:
文件名: src/main.rs
fn main() {
let x = plus_one(5);
println!("The value of x is: {x}");
}
fn plus_one(x: i32) -> i32 {
x + 1;
}
编译此代码会产生错误,如下所示:
$ cargo run
Compiling functions v0.1.0 (file:///projects/functions)
error[E0308]: mismatched types
--> src/main.rs:7:24
|
7 | fn plus_one(x: i32) -> i32 {
| -------- ^^^ expected `i32`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
8 | x + 1;
| - help: remove this semicolon to return this value
For more information about this error, try `rustc --explain E0308`.
error: could not compile `functions` (bin "functions") due to 1 previous error
主要错误消息mismatched types
揭示了这个
法典。函数的定义plus_one
表示它将返回一个i32
,但语句的计算结果不为值,该值由 表示 ,
单位类型。因此,不会返回任何内容,这与函数
定义并导致错误。在此输出中,Rust 向
可能有助于纠正这个问题:它建议删除分号,它
将修复错误。()
本文档由官方文档翻译而来,如有差异请以官方英文文档(https://doc.rust-lang.org/)为准