在編程中,函數(shù)是一段執(zhí)行特定任務(wù)的代碼,它是大多數(shù)編程語(yǔ)言中的基本構(gòu)建塊之一。在Rust中,函數(shù)也是組織代碼和實(shí)現(xiàn)邏輯的關(guān)鍵工具。
函數(shù)就是一種過(guò)程抽象。舉個(gè)例子,開鎖就是指代,你掏出鑰匙,插入鑰匙孔,順時(shí)針旋轉(zhuǎn)鑰匙,這一系列復(fù)雜過(guò)程。用開鎖兩個(gè)字抽象了你的復(fù)雜操作。
基本語(yǔ)法
Rust中的函數(shù)定義的基本語(yǔ)法如下:
fn function_name(parameters) -> return_type {
// 函數(shù)體
}
-
fn關(guān)鍵字用于聲明一個(gè)函數(shù)。 -
function_name是函數(shù)的名稱。 -
parameters是傳遞給函數(shù)的參數(shù)列表,用括號(hào)括起來(lái),多個(gè)參數(shù)用逗號(hào)分隔。 -
->運(yùn)算符后跟return_type,表示函數(shù)返回值的類型。 -
{}中的是函數(shù)體,包含了執(zhí)行任務(wù)的代碼。
示例1:無(wú)參數(shù)無(wú)返回值的函數(shù)
fn greet() {
println!("Hello, world!");
}
-
fn:這是Rust中聲明函數(shù)的關(guān)鍵字。 -
greet:這是函數(shù)的名稱。 -
():括號(hào)內(nèi)是函數(shù)的參數(shù)列表。在這個(gè)例子中,greet函數(shù)不接受任何參數(shù),所以括號(hào)內(nèi)為空。 -
{}:大括號(hào)內(nèi)是函數(shù)的主體,也就是函數(shù)執(zhí)行時(shí)運(yùn)行的代碼。在這個(gè)例子中,函數(shù)的主體是一條打印"Hello, world!"到控制臺(tái)的語(yǔ)句。 -
;:在Rust中,除了函數(shù)主體和表達(dá)式的結(jié)尾,大多數(shù)語(yǔ)句都需要以分號(hào);結(jié)束。由于greet函數(shù)的主體是一個(gè)表達(dá)式(println!宏調(diào)用),所以這里不需要分號(hào)。
示例2:帶參數(shù)和返回值的函數(shù)
fn add(a: i32, b: i32) -> i32 {
a + b
}
-
fn:聲明函數(shù)的關(guān)鍵字。 -
add:函數(shù)的名稱。 -
(a: i32, b: i32):括號(hào)內(nèi)是參數(shù)列表。這里add函數(shù)接受兩個(gè)參數(shù),a和b,它們都是32位整數(shù)(i32是Rust中32位整數(shù)的類型)。 -
-> i32:箭頭->后面跟著的是函數(shù)的返回類型。在這個(gè)例子中,add函數(shù)返回一個(gè)32位整數(shù)。 -
{ a + b }:函數(shù)的主體是一個(gè)表達(dá)式,它將兩個(gè)參數(shù)a和b相加。由于這是一個(gè)表達(dá)式,并且是函數(shù)的唯一語(yǔ)句,Rust會(huì)自動(dòng)返回這個(gè)表達(dá)式的結(jié)果。
在這兩個(gè)例子中,greet函數(shù)是一個(gè)簡(jiǎn)單的函數(shù),它不接受任何參數(shù),也沒(méi)有返回值。而add函數(shù)接受兩個(gè)參數(shù),計(jì)算它們的和,并返回這個(gè)和。在Rust中,函數(shù)的返回值是通過(guò)返回值類型的表達(dá)式隱式返回的,不需要使用return關(guān)鍵字。
函數(shù)特性
- 表達(dá)式 vs 語(yǔ)句:在Rust中,函數(shù)體的最后一個(gè)表達(dá)式不需要分號(hào),這意味著它將作為返回值。如果加上分號(hào),它就變成了語(yǔ)句,不會(huì)返回任何值。
- 參數(shù)類型:Rust是靜態(tài)類型語(yǔ)言,函數(shù)參數(shù)和返回值都必須明確指定類型。
-
返回值:如果函數(shù)不需要返回值,可以省略
-> return_type部分,或者使用()作為返回類型。
函數(shù)的調(diào)用
fn main() {
let result = level_one();
println!("最終結(jié)果是: {}", result);
}
fn level_one() -> i32 {
let partial_result = level_two();
// 做一些處理
partial_result + 10
}
fn level_two() -> i32 {
let partial_result = level_three();
// 做一些處理
partial_result * 2
}
fn level_three() -> i32 {
// 假設(shè)這是最低層的函數(shù),它不調(diào)用其他函數(shù)
5
}
在這個(gè)例子中:
-
main調(diào)用level_one函數(shù)。 -
level_one函數(shù)調(diào)用level_two函數(shù)。 -
level_two函數(shù)調(diào)用level_three函數(shù)。 -
level_three函數(shù)是最低層的函數(shù),它不調(diào)用其他函數(shù)。
每個(gè)函數(shù)執(zhí)行一些操作,然后可能將結(jié)果傳遞給調(diào)用它的函數(shù)。最終,main函數(shù)打印出最終的結(jié)果。
這種層層調(diào)用的方式可以幫助你組織代碼,使其更加模塊化和可維護(hù)。
函數(shù)調(diào)用修改習(xí)題代碼
//修改前
fn practice_loop_statement_01(){
println!("1到10的整數(shù)。");
for i in 1..=10{
println!("{}",i);
}
}
//修改后
fn practice_loop_statement_01(){
println!("1到10的整數(shù)。{}",get_string(10));
}
fn get_string(number:usize)->String{
let mut result = String::new();
for i in 1..=number{
result += &format!("\n{}", i);
}
result
}
- "\n"是轉(zhuǎn)義符號(hào),一種特殊的字符,含義是換行
- 這么改的好處是什么?你只要關(guān)心get_string這個(gè)名字和參數(shù)10。不需要考慮其他
- 而修改前,你還需要關(guān)心for循環(huán)干了什么事情。這是簡(jiǎn)單代碼你覺(jué)得沒(méi)什么,一旦邏輯復(fù)雜起來(lái)就非常痛苦了。
- 說(shuō)到底這種修改對(duì)于機(jī)器來(lái)說(shuō)是脫了褲子放屁,多此一舉。
- 但對(duì)于編程人員來(lái)說(shuō),少了理解的心智負(fù)擔(dān)。你只需要記得給10,函數(shù)給你1到10的字符就行了。用的時(shí)候不用關(guān)心它到底怎么實(shí)現(xiàn)的。
- 這很符合人理解事物的思維習(xí)慣,從一堆操作中抽象一個(gè)概念,再組合概念形成新的概念。