解構列舉
就像元組,結構體和列舉也可透過配對來解構:
結構體
struct Foo { x: (u32, u32), y: u32, } #[rustfmt::skip] fn main() { let foo = Foo { x: (1, 2), y: 3 }; match foo { Foo { x: (1, b), y } => println!("x.0 = 1, b = {b}, y = {y}"), Foo { y: 2, x: i } => println!("y = 2, x = {i:?}"), Foo { y, .. } => println!("y = {y}, other fields were ignored"), } }
列舉
模式也可用來將變數綁定至值的某些部分。您可以透過這個方式檢查型別的結構。首先從簡單的 enum
型別開始吧:
enum Result { Ok(i32), Err(String), } fn divide_in_two(n: i32) -> Result { if n % 2 == 0 { Result::Ok(n / 2) } else { Result::Err(format!("cannot divide {n} into two equal parts")) } } fn main() { let n = 100; match divide_in_two(n) { Result::Ok(half) => println!("{n} divided in two is {half}"), Result::Err(msg) => println!("sorry, an error happened: {msg}"), } }
這裡我們利用分支來「解構」Result
值。在第一個分支中,half
會與 Ok
變體中的值綁定。在第二個分支中,msg
會綁定至錯誤訊息。
This slide should take about 8 minutes.
結構體
- 請變更
foo
中的常值,與其他模式配對。 - 在
Foo
中新增一個欄位,並視需要變更模式。 - 捕獲和常數運算式之間的區別可能不容易發現。請嘗試將第二個分支的
2
變更為變數,您會發現它幾乎無法運作。現在將其變更為const
,您會看到它再次運作。
列舉
重要須知:
if
/else
運算式會傳回列舉,之後列舉會透過match
解除封裝。- 您可以嘗試在列舉定義中加入第三個變體,並在執行程式碼時顯示錯誤。請向學員指出程式碼現在有哪些地方還不詳盡,並說明編譯器會如何嘗試給予提示。
- The values in the enum variants can only be accessed after being pattern matched.
- Demonstrate what happens when the search is inexhaustive. Note the advantage the Rust compiler provides by confirming when all cases are handled.
- 將
divide_in_two
的結果儲存在result
變數中,並在迴圈中match
結果。由於配對符合時會耗用msg
,因此這麼做並不會執行編譯。如要修正此問題,請配對&result
,而非result
。這會讓msg
成為參照,因此就不會遭到耗用。這個「人因工程學的配對」功能已於 Rust 2018 推出。如要支援舊版 Rust,請在模式中將msg
替換成ref msg
。