歡迎回到 Rust 的世界,我們今天來學 if 表達式。
上一篇:02_functions
本系列主頁面:Rust繁中簡學!
繁體中文版 Rustlings:https://github.com/TimLai666/rustlings-zh-TW
安裝方法:00_intro
03_if
If
if
是最基本(但仍然非常多用途!)的控制流類型,您將在這裡學習它。進一步了解
單元的說明真是一次比一次簡潔😅
練習一(if1.rs)
// if1.rs // // 執行 `rustlings hint if1` 或使用 `hint` watch 子命令來獲取提示。 // I AM NOT DONE pub fn bigger(a: i32, b: i32) -> i32 { // 完成此函數以返回較大的數字! // 如果兩個數字相等,可以返回任意一個。 // 不要使用: // - 其他函數調用 // - 其他變數 } // 暫時不用管這個 :) #[cfg(test)] mod tests { use super::*; #[test] fn ten_is_bigger_than_eight() { assert_eq!(10, bigger(10, 8)); } #[test] fn fortytwo_is_bigger_than_thirtytwo() { assert_eq!(42, bigger(32, 42)); } #[test] fn equal_numbers() { assert_eq!(42, bigger(42, 42)); } }
⚠️ 編譯 exercises/03_if/if1.rs 失敗!請再試一次。以下是輸出: error[E0308]: mismatched types --> exercises/03_if/if1.rs:7:34 | 7 | pub fn bigger(a: i32, b: i32) -> i32 { | ------ ^^^ expected `i32`, found `()` | | | implicitly returns `()` as its body has no tail or `return` expression | note: consider returning one of these bindings --> exercises/03_if/if1.rs:7:15 | 7 | pub fn bigger(a: i32, b: i32) -> i32 { | ^ ^ error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`.
這題有個 bigger
函數,我們必須完成它,讓他回傳兩個數中比較大的數。
這個簡單,我們寫一個 if 來判斷 a 有沒有大於 b。如果有,就回傳 a,否則就回傳 b。
// if1.rs // // 執行 `rustlings hint if1` 或使用 `hint` watch 子命令來獲取提示。 // I AM NOT DONE pub fn bigger(a: i32, b: i32) -> i32 { // 完成此函數以返回較大的數字! // 如果兩個數字相等,可以返回任意一個。 // 不要使用: // - 其他函數調用 // - 其他變數 if a > b { return a; } else { return b; } } // 暫時不用管這個 :) #[cfg(test)] mod tests { use super::*; #[test] fn ten_is_bigger_than_eight() { assert_eq!(10, bigger(10, 8)); } #[test] fn fortytwo_is_bigger_than_thirtytwo() { assert_eq!(42, bigger(32, 42)); } #[test] fn equal_numbers() { assert_eq!(42, bigger(42, 42)); } }
進度: [########>---------------------------------------------------] 13/96 (13.5 %) ✅ 成功測試 exercises/03_if/if1.rs! 🎉 🎉 代碼正在編譯,並且測試通過! 🎉 🎉 您可以繼續進行此練習, 或通過刪除 `I AM NOT DONE` 註釋來進入下一個練習: 3 | // 執行 `rustlings hint if1` 或使用 `hint` watch 子命令來獲取提示。 4 | 5 | // I AM NOT DONE 6 | 7 | pub fn bigger(a: i32, b: i32) -> i32 {
第一題就這樣完成了。觀察程式碼可以發現,Rust 的 if 表達式的條件不需要加小括號。
練習二(if2.rs)
// if2.rs // // 第一步:讓我編譯通過! // 第二步:讓 bar_for_fuzz 和 default_to_baz 測試通過! // // 執行 `rustlings hint if2` 或使用 `hint` watch 子命令來獲取提示。 // I AM NOT DONE pub fn foo_if_fizz(fizzish: &str) -> &str { if fizzish == "fizz" { "foo" } else { 1 } } // 不需要更改測試! #[cfg(test)] mod tests { use super::*; #[test] fn foo_for_fizz() { assert_eq!(foo_if_fizz("fizz"), "foo") } #[test] fn bar_for_fuzz() { assert_eq!(foo_if_fizz("fuzz"), "bar") } #[test] fn default_to_baz() { assert_eq!(foo_if_fizz("literally anything"), "baz") } }
⚠️ 編譯 exercises/03_if/if2.rs 失敗!請再試一次。以下是輸出: error[E0308]: mismatched types --> exercises/03_if/if2.rs:14:9 | 10 | pub fn foo_if_fizz(fizzish: &str) -> &str { | ---- expected `&str` because of return type ... 14 | 1 | ^ expected `&str`, found integer error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`.
這題的問題在於函數回傳值的資料型態和一開始將好的不同。
我們觀察一下程式碼,更改 if 表達式,讓程式依據不同情況回傳對應的字串。
// if2.rs // // 第一步:讓我編譯通過! // 第二步:讓 bar_for_fuzz 和 default_to_baz 測試通過! // // 執行 `rustlings hint if2` 或使用 `hint` watch 子命令來獲取提示。 // I AM NOT DONE pub fn foo_if_fizz(fizzish: &str) -> &str { if fizzish == "fizz" { "foo" } else if fizzish == "fuzz" { "bar" } else { "baz" } } // 不需要更改測試! #[cfg(test)] mod tests { use super::*; #[test] fn foo_for_fizz() { assert_eq!(foo_if_fizz("fizz"), "foo") } #[test] fn bar_for_fuzz() { assert_eq!(foo_if_fizz("fuzz"), "bar") } #[test] fn default_to_baz() { assert_eq!(foo_if_fizz("literally anything"), "baz") } }
我們在 fizzish
為 "fizz"
的時候回傳 "foo"
, fizzish
為 "fuzz"
的時候回傳 "bar"
,其他時候則回傳 "baz"
。
進度: [########>---------------------------------------------------] 14/96 (14.6 %) ✅ 成功測試 exercises/03_if/if2.rs! 🎉 🎉 代碼正在編譯,並且測試通過! 🎉 🎉 您可以繼續進行此練習, 或通過刪除 `I AM NOT DONE` 註釋來進入下一個練習: 6 | // 執行 `rustlings hint if2` 或使用 `hint` watch 子命令來獲取提示。 7 | 8 | // I AM NOT DONE 9 | 10 | pub fn foo_if_fizz(fizzish: &str) -> &str {
練習三(if3.rs)
// if3.rs // // 執行 `rustlings hint if3` 或使用 `hint` watch 子命令來獲取提示。 // I AM NOT DONE pub fn animal_habitat(animal: &str) -> &'static str { let identifier = if animal == "螃蟹" { 1 } else if animal == "地鼠" { 2.0 } else if animal == "蛇" { 3 } else { "未知" }; // 請勿更改下面的這條語句 let habitat = if identifier == 1 { "海灘" } else if identifier == 2 { "地洞" } else if identifier == 3 { "沙漠" } else { "未知" }; habitat } // 不需要更改測試。 #[cfg(test)] mod tests { use super::*; #[test] fn gopher_lives_in_burrow() { assert_eq!(animal_habitat("地鼠"), "地洞") } #[test] fn snake_lives_in_desert() { assert_eq!(animal_habitat("蛇"), "沙漠") } #[test] fn crab_lives_on_beach() { assert_eq!(animal_habitat("螃蟹"), "海灘") } #[test] fn unknown_animal() { assert_eq!(animal_habitat("恐龍"), "未知") } }
⚠️ 編譯 exercises/03_if/if3.rs 失敗!請再試一次。以下是輸出: error[E0308]: `if` and `else` have incompatible types --> exercises/03_if/if3.rs:15:9 | 12 | } else if animal == "蛇" { | ____________- 13 | | 3 | | - expected because of this 14 | | } else { 15 | | "未知" | | ^^^^^^ expected integer, found `&str` 16 | | }; | |_____- `if` and `else` have incompatible types error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0308`.
這題因為 if 表達式回傳的值不一致而出錯,包括 2.0
是浮點數,而 "未知"
是字串。我們把它們都改成整數即可。
// if3.rs // // 執行 `rustlings hint if3` 或使用 `hint` watch 子命令來獲取提示。 // I AM NOT DONE pub fn animal_habitat(animal: &str) -> &'static str { let identifier = if animal == "螃蟹" { 1 } else if animal == "地鼠" { 2 } else if animal == "蛇" { 3 } else { 0 }; // 請勿更改下面的這條語句 let habitat = if identifier == 1 { "海灘" } else if identifier == 2 { "地洞" } else if identifier == 3 { "沙漠" } else { "未知" }; habitat } // 不需要更改測試。 #[cfg(test)] mod tests { use super::*; #[test] fn gopher_lives_in_burrow() { assert_eq!(animal_habitat("地鼠"), "地洞") } #[test] fn snake_lives_in_desert() { assert_eq!(animal_habitat("蛇"), "沙漠") } #[test] fn crab_lives_on_beach() { assert_eq!(animal_habitat("螃蟹"), "海灘") } #[test] fn unknown_animal() { assert_eq!(animal_habitat("恐龍"), "未知") } }
進度: [#########>--------------------------------------------------] 15/96 (15.6 %) ✅ 成功測試 exercises/03_if/if3.rs! 🎉 🎉 代碼正在編譯,並且測試通過! 🎉 🎉 您可以繼續進行此練習, 或通過刪除 `I AM NOT DONE` 註釋來進入下一個練習: 3 | // 執行 `rustlings hint if3` 或使用 `hint` watch 子命令來獲取提示。 4 | 5 | // I AM NOT DONE 6 | 7 | pub fn animal_habitat(animal: &str) -> &'static str {
錯誤消失了,並且我們發現下列語法:
let identifier = if animal == "螃蟹" { 1 } else if animal == "地鼠" { 2 } else if animal == "蛇" { 3 } else { 0 };
Rust 的 if 表達式是可以接在變數宣告後面的,根據不同條件賦予變數不同的值,只不過它們的資料型態似乎必須一樣。
總結
if 表達式的練習結束了,重點摘要如下:
- Rust 的 if 表達式的條件不需要加小括號。
- Rust 的 if 表達式可以接在變數宣告後面,根據不同條件賦予變數不同的值。
- if 表達式的回傳值資料型態必須一致。
One Comment