Control Flow
控制流程 (Control Flow) 是順序控制程式中不可或缺的一部分。以下將介紹程式語言中會出現的流程語法。所謂順序控制,表示程式是依序執行,習慣會從上到下、從左到右,以利閱讀。以下會搭配可執行的 Rust 語言程式碼來示範。
do first;
do next;
first; second; third;
Goto Statement
跳轉語句是較為原始的控制方式,然而這種直接跳轉的方式比較破壞閱讀和程式的嚴謹,所以通常只在底層使用。此語法需要設定一個位置(如 C / C++ 中稱為 label)再藉由 goto
語句跳轉,由於此位置可以在 goto
前後,較不易控制。在迴圈語句中可用來跳脫迴圈,參見該章節以取得更多說明。
關於更多 goto
語法,可以參考 ANSI C 對於跳轉語句 (jump statement) 的說明。
Condition Statement
判斷句是由一個布林值 (boolean),也就是 true 和 false 兩個值判斷程式的前進方向,藉此組合出不同的執行效果,最常見的就是 if
else
語句。判斷句可以藉由交疊形成多種判斷,如 C / C++ 中的 switch
case
語句等等。
#![allow(unused)] fn main() { // 一次判斷 if true { println!("do something if true"); } // 一次判斷,包含例外 if true { println!("do something if true"); } else { println!("do something if false"); } // 兩次判斷,包含例外 if false { println!("case 1"); } else if true { println!("case 2"); } else { println!("case 3"); } }
Pattern Matching
類似於 if
else
的組合,但是通常配合列舉 (enumeration) 的類型做主軸,可以設定保護條件 (guard condition),甚至是解包 (unpack) 內含的資料。
#![allow(unused)] fn main() { enum Color { Red, Black, White, // Rust 允許攜帶資料的選項 Other(u8, u8, u8), } let color = Color::OTHER(162, 33, 22); match color { Color::Red => { println!("red"); } Color::Black => { println!("black"); } Color::White => { println!("white"); } // 匹配定值 Color::Other(0, 0, 0) => { println!("black"); } Color::Other(255, 255, 255) => { println!("white"); } // 按順序解開攜帶的資料 Color::Other(r, g, b) => { println!("color ({}, {}, {})", r, g, b); } } }
在單一匹配的時候,Rust 可以使用 if let
語句,當然不限於 enum
類型,解包或單純的付值也可以,只是會變成 if true
或 if false
可簡化的情況。
#![allow(unused)] fn main() { struct Color(u8, u8, u8); let color = Color(162, 33, 22); if let Color(r, g, b) = color { println!("color ({}, {}, {})", r, g, b); } }
Loop
迴圈可以一直重複程式區段,技術上來說是無法中斷的,必須依靠跳轉語句。為了迴圈而設計的跳轉語句通常為兩種,只跳過當前區段的為 continue
;離開迴圈的為 break
。
#![allow(unused)] fn main() { loop { if true { println!("break now!"); break; } } }
延伸條件的迴圈為 while
迴圈,即為在一開始檢查條件,條件為 true
時就會繼續循環。
#![allow(unused)] fn main() { let mut b = true; while b { println!("run once"); b = false; } }
另外迭代器 (iterator) 便是一種針對迴圈設計的資料結構,能夠按順序取得數值。序列 (sequence) 和映射 (map) 都可以轉換成迭代器,在 Rust 中,into_iter()
和 iter()
等方法可以轉換成迭代器。
#![allow(unused)] fn main() { for i in [1, 2, 3] { println!("{}", i); } // for-loop 等同於 let mut iter = [1, 2, 3].into_iter(); while let Some(&i) = iter.next() { println!("{}", i); } }
上面的 while let
語句是結合 while
迴圈與 if let
,直到匹配失敗才會跳脫迴圈。