跳轉到內容

Rust 新手程式設計/模式匹配

100% developed
來自華夏公益教科書,開放的書籍,開放的世界

模式匹配

[編輯 | 編輯原始碼]

我們之前建立了 AngleType 列舉。假設我們想列印一些關於角度的解釋。為了根據遇到的列舉變體來改變這個解釋,我們可以使用 match 語句。例如

 fn print_angle_info(points: Points) {
     match points.angle_type {
         AngleType::Acute => {
             println!("This angle is an acute angle; one of less than 90 degrees!");
         },
         AngleType::Right(axis_aligned) => {
             if axis_aligned {
                 println!("This angle is an axis-aligned right angle, exactly 90 degrees!");
             } else {
                 println!("This angle is a non axis-aligned right angle, exactly 90 degrees!");
             }
         },
         AngleType::Obtuse => {
             println!("This angle is an obtuse one. That means it more than 90 degrees, but less than 180.");
         },
         AngleType::Reflex => {
             println!("This angle is a reflex angle. That means it's very large: more than 180 degrees :O");
         }
     }
 }

如果角度型別是每個程式碼塊中描述的型別,那麼我們就進入那個程式碼塊的 {} 中,忽略其他所有 {}。例如,如果我們有一個角度型別為銳角的點,我們只會打印出銳角部分。還要注意,由於直角有一個布林值附加,我們可以使用一個名為 axis_aligned 的變數,該變數被設定為該值的任何值。然後我們可以在 {} 中使用它來列印更多關於角度的資訊。注意,我們匹配列舉的所有變體。這是 match 語句的要求。為了說明這一點,我們可以匹配以下函式中的數字

 fn print_specific_number_facts(num: u8) {
     match num {
         0 => println!("The number representing nothingness"),
         2 => println!("The only even prime number!"),
         6 => println!("A perfect number"),
     }
 }

首先要注意,我並沒有在行上新增 {}。這是因為我們只有一個匹配數字後的單行,所以我們可以省略它們,但我們必須在行尾新增逗號。這將無法編譯,因為它不知道如果我們得到一個不是 1、2 或 6 的數字該怎麼辦。如果我們想要它在接收沒有事實的數字時什麼也不做,我們可以明確地說

 fn print_specific_number_facts(num: u8) {
     match num {
         0 => println!("The number representing nothingness"),
         2 => println!("The only even prime number!"),
         6 => println!("A perfect number"),
         _ => {},
     }
 }

下劃線充當匹配所有,空 {} 表示我們不想在這種情況下執行任何操作。我們也可以在其他地方使用下劃線。還記得上一頁的 is_angle_right 函式嗎?作為參考,這是它之前的程式碼

 fn is_angle_right(points: Points) -> bool {
     points.angle_type == AngleType::Right
 }

這不再有效,因為我們可以有 AngleType::Right(true) 或 AngleType::Right(false)。與其分別匹配這兩個,我們可以把它改為

 fn is_angle_right(points: Points) -> bool {
     points.angle_type == AngleType::Right(_)
 }

此外,如果我們想要檢查只對特定列舉變體執行某些操作並使用內部值(s)。一個方便的方法來描述這種模式是使用 'if let'。

 fn print_right_angle(points: Points) {
     if let AngleType::Right(axis_aligned) = points.angle_type {
          if axis_aligned {
              println!("axis aligned right angle");
          } else {
              println!("non axis aligned right angle");
          }
     } else {
         println!("Some other angle");
     }
 }

這對描述這種模式非常方便,也很容易閱讀。還有許多其他的列舉和結構模式,以及許多與這些模式匹配的方法,但這些是組織和結構化 Rust 中資料的基本構建塊。

下一步: 引用和借用的基礎

華夏公益教科書