This article is part of the Rust學習筆記 series.

理所當然地,Rust提供了條件、循環等控制流程。由於enum的特殊點(可以承載數據),Rust的條件結構爲其有專門的設計,所以也在此簡單介紹enum。

但壽元、所有權、引用借用等概念也影響enum的實際使用,故而會在Rust學習筆記/再敘enum和模式匹配再次討論。

條件結構

if 表達式

if 後接一個 bool 類型的表達式(不需要括號),且 ifelse 子句(均爲表達式)均需要大括號。特殊地,如要書寫 else-if ,則 else if 合併爲一個表達式。

...
let m = if a < 5 {
  println!("a小於5");
  4
} else if a < 8 {
  println!("a小於8");
  7
} else {
  10
}
println!("m={}", m);

注意 if 各子句(表達式)的返回值應當是相同的類型,否則會造成編譯錯誤(類型錯誤)。

另外, if 表達式還支持與enum聯合使用的模式匹配,使用 if let 語法,見下文enum部分。

模式匹配(match)

Rust的 match 基本就是其他語言中的 switch,但和其他語言相比多了對條件的完備性檢查:必須匹配所有的可能性。另外,類似於 ifmatch 也是表達式。

let x = 5;

let number = match x {
    1 => "one",
    2 => "two",
    3 => "three",
    4 => "four",
    5 => "five",
    _ => "anything else",
};

上面代碼展示了match的基本語法,其中_代表「任何」(也就是其他語言中的default)。

理論上來說,同一枝匹配的「模式」也可以是多值,比如如下的例子:

match x {
    1 | 2 => "one or two",
    3 ..= 9 => "three to nine",
    _ => "anything else",
};

注意這裏的範圍是用「範圍模式」而非「 範圍表達式」寫就的。官方文檔的內容預示着還有更高級的形式,有興趣的可以去翻閱文檔。

當涉及enum後,match則起到更大的作用(見下文)。

循環結構

Rust支持三種循環結構 loopwhilefor

loop

loop 產生一個無限循環,等價於C中的 while (1)

fn main() {
    loop {
        println!("again!");
    }
}

來自 官方教程控制流程一節

while

while 就是正常的 while 結構,不進行贅述。

if 一樣,其條件表達式也不需要括號;同 if 一樣,其也支持 while let 語法進行模式匹配(見下面enum部分)。

for

for 就是 for each。同Python中的寫法類似,Rust中也需要 for ... in ...

fn main() {
    let a = [10, 20, 30, 40, 50];

    for element in a.iter() {
        println!("the value is: {}", element);
    }
}
fn main() {
    for number in (1..4).rev() {
        println!("{}!", number);
    }
    println!("LIFTOFF!!!");
}

同樣來自 官方教程控制流程一節

enum

Rust的enum可以簡單承載數據,這使得它承擔了一些很有意義的其他功能。

比如說,Rust中沒有null(不是改名這種文字遊戲),取而代之的則是一個叫做Option<T>的enum,其有效取值分別是Some(T)None(和你想得一樣,這裏的<T>是泛型參數,而(T)則是我們說到的數據承載)。由於泛型和強類型兩項特性,這一設定帶來兩個結論:

  1. None不能越過類型邊界
  2. Some(T)None必須分別處理,否則編譯無法通過

於是,對Java等語言中普遍存在的空指針問題,Rust程序員完全不需要擔心:編譯時就需要確認數據是否存在,運行時一定不會出現空指針。

特殊設計的 if let 等結構便是配合這類機制的良方,方便寫出簡短的代碼:

let some_value = Some(3);

if let None = some_value {
    println!("some_value is None")
}

if let Some(x) = some_value {
    println!("{}", x);
}


let some_value2 = Some("test");

match some_value2 {
    Some(s) => println!("{}", s),
    None => println!("None!"),
}

可以看到,這裏的控制流程的判定條件是該賦值是否成功,並且變量x被自動解包賦值(3,而非Some(3))。 另外,這裏的match並沒有使用_,因爲Rust編譯器知道some_value2是一個Option類型(更具體的,Option<&'static str>類型)的值,其可能取值只有兩種。

Renyuneyun

Arch Linux用戶;閒暇時爲FLOSS做做貢獻;認同自由軟件理念。自認唯物論者;反對任意形式的迷信;在意社會問題;拒絕先入爲主。

Renyuneyun

Join the discussion