参数,语句和表达式,返回值
尽管rust
是一门多范式的编程语言,但rust
的编程风格是更偏向于函数式的,函数在rust
中是一等公民(first-class)
。这意味着,函数是可以作为数据在程序中进行传递,如:作为函数的参数。跟C、C++
一样,rust
程序也有一个唯一的程序入口main
函数。rust
的main
函数形式如下:
fn main() {
}
rust
使用 fn
关键字来声明和定义函数,fn
关键字隔一个空格后跟函数名,函数名后跟着一个括号,函数参数定义在括号内。rust
使用snake_cas
e风格来命名函数,即所有字母小写并使用下划线类分隔单词,如:foo_bar
。如果函数有返回值,则在括号后面加上箭头 ->
,在箭头后加上返回值的类型。
rust
的函数参数声明和一般的变量声明相仿,也是参数名后加冒号,冒号后跟参数类型,不过不需要let
关键字。需要注意的是,普通变量声明(let语句
)是可以省略变量类型的,而函数参数的声明则不能省略参数类型。 来看一个简单例子:
fn main() {
say_hi("ruster");
}
fn say_hi(name: &str) {
println!("Hi, {}", name);
}
尝试运行程序,将会输出如下内容:
$ cargo run
Compiling variables v0.1.0 (/projects/variables)
Finished dev [unoptimized + debuginfo] target(s) in 0.59s
Running `target/debug/variables`
Hi, ruster
上例中,say_hi
函数拥有一个参数,名为name
,类型为&str
。
rust
是一个基于表达式的语言,不过它也有语句。rust
只有两种语句:声明语句和表达式语句,其他的都是表达式。基于表达式是函数式语言的一个重要特征,表达式总是返回值
。
变量声明语句,主要是指let
语句,如:
let a = 8;
let b: Vec<f64> = Vec::new();
let (a, c) = ("hi", false);
由于let
是语句,所以不能将let
语句赋给其他值。如下形式是错误的:
let b = (let a = 8);
当运行这个程序时,会得到如下错误:
$ cargo run
Compiling variables v0.1.0 (/projects/variables)
error: expected expression, found `let` statement
--> src/main.rs:2:14
|
2 | let b = (let a = 8);
| ^^^
error: expected expression, found statement (`let`)
--> src/main.rs:2:14
|
2 | let b = (let a = 8);
| ^^^^^^^^^
|
= note: variable declaration using `let` is a statement
error[E0658]: `let` expressions in this position are unstable
--> src/main.rs:2:14
|
2 | let b = (let a = 8);
| ^^^^^^^^^
|
= note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
warning: unnecessary parentheses around assigned value
--> src/main.rs:2:13
|
2 | let b = (let a = 8);
| ^ ^
|
= note: `#[warn(unused_parens)]` on by default
help: remove these parentheses
|
2 - let b = (let a = 8);
2 + let b = let a = 8;
|
For more information about this error, try `rustc --explain E0658`.
warning: `variables` (bin "variables") generated 1 warning
error: could not compile `variables` due to 3 previous errors; 1 warning emitted
表达式会计算出一个值,并且你将编写的大部分 Rust 代码是由表达式组成的。函数调用是一个表达式。宏调用是一个表达式。用大括号创建的一个新的块作用域也是一个表达式,例如:
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
函数中没有函数调用、宏、甚至没有 let
语句 —— 只有数字 5
。这在 Rust
中是一个完全有效的函数。注意,也指定了函数返回值的类型,就是-> i32
。尝试运行代码;输出应该看起来像这样:
$ cargo run
Compiling variables v0.1.0 (/projects/variables)
Finished dev [unoptimized + debuginfo] target(s) in 0.30s
Running `target/debug/variables`
The value of x is: 5
让我们看看另一个例子:
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 variables v0.1.0 (/projects/variables)
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 `variables` due to previous error
主要的错误信息,“mismatched types”
(类型不匹配),揭示了代码的核心问题。函数 plus_one
的定义说明它要返回一个 i32
类型的值,不过语句并不会返回值,使用单位类型 () 表示不返回值。因为不返回值与函数定义相矛盾,从而出现一个错误。在输出中,Rust
提供了一条信息,可能有助于纠正这个错误:它建议删除分号(推荐)或者改为return x + 1;
,这会修复这个错误。
Rust
的函数不支持多返回值,但是我们可以利用元组来返回多个值,配合Rust
的模式匹配,使用起来十分灵活。先看例子
fn main() {
let (p2, p3) = pow_2_3(789);
println!("pow 2 of 789 is {}.", p2);
println!("pow 3 of 789 is {}.", p3);
}
fn pow_2_3(n: i32) -> (i32, i32) {
(n * n, n * n * n)
}
可以看到,上例中,pow_2_3
函数接收一个i32
类型的值,返回其二次方和三次方的值,这两个值包装在一个元组中返回。在main函数中,let
语句就可以使用模式匹配将函数返回的元组进行解构,将这两个返回值分别赋给p2
和p3
,从而可以得到789
二次方的值和三次方的值。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!