Rust 函数详解
前言
Rust 支持多种编程范式,但更偏向于函数式,函数在 Rust 中是“一等公民”,函数可以作为数据在程序中进行传递。跟 C、C++ 一样, Rust 也有一个唯一的程序入口 main 函数。
示例:程序入口main函数
在Rust中使用fn关键字来声明和定义函数,函数名以snak case风格进行命名,使用小写字母以及下划线分割单词
fn main(){
println!("Hello,World!");
}
自定义函数
格式:fn + 空格 + 函数名()->类型{}
,其中函数返回类型为空可以省略,返回类型默认为()
示例:
// 入口函数
fn main(){
say_hello();
say_hello_default();
}
// 自定义函数
fn say_hello()->(){
println!("Hello,Rust!");
}
// 定一个带有返回类型的函数
fn say_hello_default()->(){
println!("Hello,Rust!");
}
函数参数
当然Rust的函数也可以有参数,并且每一个函数都有返回值
格式:参数名+冒号+类型
示例: 声明一个函数say_hello
,接受一个参数name
// 默认入口函数
fn main() {
println!("Hello, world!");
say_hello("Lei");
}
// 定一个函数
fn say_hello(name: &str){
println!("Hello {}", name);
}
函数返回值
当然在Rust中也有返回值,在Rust中每个函数都有一个返回值,其中main入口函数也不例外,默认main的入口函数返回值是()一个空元组;注意当Rust中的函数返回()可以在声明函数是可以直接省略返回类型的声明。
可省略完整版
示例:
// 默认入口函数
fn main() -> () {
println!("Hello, world!");
say_hello("raymond");
}
// 定一个函数并且返回一个默认的元组`()`
fn say_hello(name: &str) -> () {
println!("Hello {}", &name);
}
有返回值的函数定义
示例:以下代码声明一个函数plus_one
并返回一个类型为i32
的值
// 默认入口函数 省略了返回类型
fn main() {
println!("Hello, world!");
let x = plus_one(5);
println!("The value of x is: {}", x);
}
// 定一个带有返回指的函数
fn plus_one(x: i32) -> i32 {
x + 1
}
使用关键字return
关键字返回
Rust中也有其他的语言的return
关键字,不过一般用于选择返回(当一段程序中存在判断分支可能提前返回并终止剩余代码的情况)
,注意如果返回位于函数末尾怎可以省略return
关键字
示例:以下代码声明一个函数,演示了带return
的返回和省略return
返回:
fn main() {
println!("Hello, world!");
let x = [1, 2, 3, 4, 5, 6, 7, 8];
println!("There is 7 in the array: {}", search(7, &x));
println!("There is 8 in the array: {}", search(8, &x));
}
// 查找列表中是否存在指定的数字
fn search(x: i32, list: &[i32]) -> bool {
for i in list {
if *i == x {
return true; // 带关键字 return 的返回使用
}
}
false // 无关键 return 的返回使用
}
无返回值的发散函数
Rust中还有一种无返回值的函数,称之为发散函数(diverging function)
。该函数不用返回任何值,使用!
作为返回类型声明。
示例:
fn main() {
println!("Hello, world!");
diverging();
println!("End");
}
fn diverging() -> ! {
panic!("This Function Will Never return");
}
输出结果:
➜ function-10 git:(master) ✗ RUST_BACKTRACE=1 cargo run
warning: unreachable statement
--> src/main.rs:4:5
|
3 | diverging();
| ----------- any code following this expression is unreachable
4 | println!("End");
| ^^^^^^^^^^^^^^^ unreachable statement
|
= note: `#[warn(unreachable_code)]` on by default
= note: this warning originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: `function-10` (bin "function-10") generated 1 warning
Finished dev [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/function-10`
Hello, world!
thread 'main' panicked at 'This Function Will Never return', src/main.rs:8:5
stack backtrace:
0: rust_begin_unwind
at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/std/src/panicking.rs:517:5
1: core::panicking::panic_fmt
at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/panicking.rs:100:14
2: function_10::diverging
at ./src/main.rs:8:5
3: function_10::main
at ./src/main.rs:3:5
4: core::ops::function::FnOnce::call_once
at /rustc/f1edd0429582dd29cccacaf50fd134b05593bd9c/library/core/src/ops/function.rs:227:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
➜ function-10 git:(master) ✗
高阶函数
高阶函数与普通函数不同之处在于,他可以使用一个或多个函数作为参数,也可以将参数作为返回值。既然函数可以作为参数和返回值,那么函数也可以作为参数和返回值,那么函数也应该有一种对应的数据类型,那么这个类型就是:函数指针类型
函数指针类型
函数指针
类型使用fn
关键字定义(声明),在编译时该类型指向一个已知函数参数和返回值类型,但函数体未知的函数。
示例:
// 定义函数
fn inc(n: i32) -> i32 {
n + 1
}
// 使用`type` 给函数指针类型起一个别名
type IncType = fn(i32) -> i32;
fn main() {
println!("Hello, world!");
// 使用函数指针类型`fn(i32) -> i32`
let func: fn(i32) -> i32 = inc;
println!("3 + 1 = {}", func(3));
// 使用函数指针类型的别名`IncType`
let func: IncType = inc;
println!("4 + 1 = {}", func(4));
}
函数作为参数
声明一个函数,以函数作为参数,起声明与普通参数一样。
示例:高阶函数
fn main() {
println!("Hello, world!");
println!("3 + 1 = {}", process(3, inc));
println!("3 - 1 = {}", process(3, dec));
}
fn inc(n: i32) -> i32 {
n + 1
}
fn dec(n: i32) -> i32 {
n - 1
}
// process 是一个高阶函数,他有两个参数,一个类型 `i32` ,另一个类型为`fn(i32)->i32`
fn process(n: i32, func: fn(i32) -> i32) -> i32 {
func(n)
}
函数作为返回值
函数作为返回值,其声明与普通函数的返回值类型声明一样。
示例:
fn main() {
println!("Hello, world!");
let a = [1, 2, 3, 4, 5, 6, 7];
let mut b = Vec::<i32>::new();
for i in &a {
b.push(get_func(*i)(*i));
}
println!("{:?}", b);
}
// 若传入的参数为偶数,返回 `inc` ,否则返回 `dec`
fn get_func(n: i32) -> fn(i32) -> i32 {
fn inc(n: i32) -> i32 {
n + 1
}
fn dec(n: i32) -> i32 {
n - 1
}
if n % 2 == 0 {
inc
} else {
dec
}
}