函數回傳值
本集目標
讓函數回傳一個值,並學會 Rust 獨特的「不加分號就是回傳值」的寫法。
正文
上一集的函數只是把結果印出來。但很多時候我們想要的是:「你算完之後把答案交回來,我自己決定要怎麼用。」
基本語法
fn add(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
let result = add(3, 4);
println!("3 + 4 = {}", result);
}
重點來了:
-> i32寫在參數後面,告訴 Rust「這個函數會回傳一個i32」- 函數最後一行
a + b沒有加分號 → 這就是回傳值
不加分號 = 回傳值
這是 Rust 最獨特的設計之一。函數最後一行如果不加分號,它的值就會自動被當成回傳值:
fn double(x: i32) -> i32 {
x * 2 // ✅ 沒有分號,這就是回傳值
}
fn main() {}
加了分號會怎樣?
如果你不小心加了分號:
fn double(x: i32) -> i32 {
x * 2; // ❌ 加了分號
}
fn main() {}
編譯器會報錯。為什麼?因為加了分號之後,x * 2 的計算結果會被丟掉,而函數最後沒有留下任何值。在這種狀況下,實際回傳的是 ()(unit type,還記得第 4 集嗎?)。但你答應了要回傳 i32,型別不符,編譯器就會抱怨。
沒寫回傳值的函數
回頭看本章第 6 集的 greet 函數,它沒有寫 -> 回傳值:
fn greet() {
println!("你好!");
}
fn main() {}
在 Rust 裡,所有函數都有回傳值。沒寫 -> 的話,就等同於寫 -> ():
fn greet() -> () {
println!("你好!");
}
fn main() {}
只是 -> () 通常省略不寫。println!("你好!"); 最後有分號,計算結果被丟掉,函數回傳 ()——剛好符合宣告。
接住回傳值
fn add(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
let result = add(3, 4);
println!("結果:{}", result);
// 也可以直接用在表達式裡
println!("再加 10:{}", add(3, 4) + 10);
}
用 tuple 回傳多個值
函數只能回傳「一個」值,但如果你想回傳多個呢?把它們裝在 tuple 裡就好:
fn swap(a: i32, b: i32) -> (i32, i32) {
(b, a)
}
fn main() {
let result = swap(1, 2);
println!("第一個:{},第二個:{}", result.0, result.1);
}
-> (i32, i32) 代表回傳一個包含兩個 i32 的 tuple。呼叫之後用 .0、.1 取出裡面的值。
再來一個實用的例子:
fn min_max(a: i32, b: i32) -> (i32, i32) {
if a < b {
(a, b)
} else {
(b, a)
}
}
fn main() {
let result = min_max(7, 3);
println!("最小:{},最大:{}", result.0, result.1);
}
重點整理
- 用
-> 型別宣告函數的回傳型別 - 函數最後一行不加分號,就是回傳值(這是 Rust 的慣用寫法)
- 加了分號就變成普通語句,回傳的會是
() - 沒寫回傳值的函數,其實回傳的是
() - 想回傳多個值?用 tuple 包起來:
-> (i32, i32),用.0、.1取值