99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

Rust 所有可能會用到模式的位置

2023-03-22 15:15 更新
ch18-01-all-the-places-for-patterns.md
commit 8a1aad812b90126974853f80d9217e07bd226650

模式出現(xiàn)在 Rust 的很多地方。你已經(jīng)在不經(jīng)意間使用了很多模式!本部分是一個所有有效模式位置的參考。

match 分支

如第六章所討論的,一個模式常用的位置是 match 表達(dá)式的分支。在形式上 match 表達(dá)式由 match 關(guān)鍵字、用于匹配的值和一個或多個分支構(gòu)成,這些分支包含一個模式和在值匹配分支的模式時運行的表達(dá)式:

match VALUE {
    PATTERN => EXPRESSION,
    PATTERN => EXPRESSION,
    PATTERN => EXPRESSION,
}

match 表達(dá)式必須是 窮盡exhaustive)的,意為 match 表達(dá)式所有可能的值都必須被考慮到。一個確保覆蓋每個可能值的方法是在最后一個分支使用捕獲所有的模式:比如,一個匹配任何值的名稱永遠(yuǎn)也不會失敗,因此可以覆蓋所有匹配剩下的情況。

有一個特定的模式 _ 可以匹配所有情況,不過它從不綁定任何變量。這在例如希望忽略任何未指定值的情況很有用。本章之后的 “忽略模式中的值” 部分會詳細(xì)介紹 _ 模式的更多細(xì)節(jié)。

if let 條件表達(dá)式

第六章討論過了 if let 表達(dá)式,以及它是如何主要用于編寫等同于只關(guān)心一個情況的 match 語句簡寫的。if let 可以對應(yīng)一個可選的帶有代碼的 else 在 if let 中的模式不匹配時運行。

示例 18-1 展示了也可以組合并匹配 if let、else if 和 else if let 表達(dá)式。這相比 match 表達(dá)式一次只能將一個值與模式比較提供了更多靈活性;一系列 if letelse if、else if let 分支并不要求其條件相互關(guān)聯(lián)。

示例 18-1 中的代碼展示了一系列針對不同條件的檢查來決定背景顏色應(yīng)該是什么。為了達(dá)到這個例子的目的,我們創(chuàng)建了硬編碼值的變量,在真實程序中則可能由詢問用戶獲得。

文件名: src/main.rs

fn main() {
    let favorite_color: Option<&str> = None;
    let is_tuesday = false;
    let age: Result<u8, _> = "34".parse();

    if let Some(color) = favorite_color {
        println!("Using your favorite color, {}, as the background", color);
    } else if is_tuesday {
        println!("Tuesday is green day!");
    } else if let Ok(age) = age {
        if age > 30 {
            println!("Using purple as the background color");
        } else {
            println!("Using orange as the background color");
        }
    } else {
        println!("Using blue as the background color");
    }
}

示例 18-1: 結(jié)合 if letelse if、else if let 以及 else

如果用戶指定了中意的顏色,將使用其作為背景顏色。如果今天是星期二,背景顏色將是綠色。如果用戶指定了他們的年齡字符串并能夠成功將其解析為數(shù)字的話,我們將根據(jù)這個數(shù)字使用紫色或者橙色。最后,如果沒有一個條件符合,背景顏色將是藍(lán)色:

這個條件結(jié)構(gòu)允許我們支持復(fù)雜的需求。使用這里硬編碼的值,例子會打印出 Using purple as the background color。

注意 if let 也可以像 match 分支那樣引入覆蓋變量:if let Ok(age) = age 引入了一個新的覆蓋變量 age,它包含 Ok 成員中的值。這意味著 if age > 30 條件需要位于這個代碼塊內(nèi)部;不能將兩個條件組合為 if let Ok(age) = age && age > 30,因為我們希望與 30 進(jìn)行比較的被覆蓋的 age 直到大括號開始的新作用域才是有效的。

if let 表達(dá)式的缺點在于其窮盡性沒有為編譯器所檢查,而 match 表達(dá)式則檢查了。如果去掉最后的 else 塊而遺漏處理一些情況,編譯器也不會警告這類可能的邏輯錯誤。

while let 條件循環(huán)

一個與 if let 結(jié)構(gòu)類似的是 while let 條件循環(huán),它允許只要模式匹配就一直進(jìn)行 while 循環(huán)。示例 18-2 展示了一個使用 while let 的例子,它使用 vector 作為棧并以先進(jìn)后出的方式打印出 vector 中的值:

    let mut stack = Vec::new();

    stack.push(1);
    stack.push(2);
    stack.push(3);

    while let Some(top) = stack.pop() {
        println!("{}", top);
    }

列表 18-2: 使用 while let 循環(huán)只要 stack.pop() 返回 Some 就打印出其值

這個例子會打印出 3、2 接著是 1。pop 方法取出 vector 的最后一個元素并返回 Some(value)。如果 vector 是空的,它返回 Nonewhile 循環(huán)只要 pop 返回 Some 就會一直運行其塊中的代碼。一旦其返回 None,while 循環(huán)停止。我們可以使用 while let 來彈出棧中的每一個元素。

for 循環(huán)

如同第三章所講的,for 循環(huán)是 Rust 中最常見的循環(huán)結(jié)構(gòu),不過還沒有講到的是 for 可以獲取一個模式。在 for 循環(huán)中,模式是 for 關(guān)鍵字直接跟隨的值,正如 for x in y 中的 x。

示例 18-3 中展示了如何使用 for 循環(huán)來解構(gòu),或拆開一個元組作為 for 循環(huán)的一部分:

    let v = vec!['a', 'b', 'c'];

    for (index, value) in v.iter().enumerate() {
        println!("{} is at index {}", value, index);
    }

列表 18-3: 在 for 循環(huán)中使用模式來解構(gòu)元組

示例 18-3 的代碼會打印出:

$ cargo run
   Compiling patterns v0.1.0 (file:///projects/patterns)
    Finished dev [unoptimized + debuginfo] target(s) in 0.52s
     Running `target/debug/patterns`
a is at index 0
b is at index 1
c is at index 2

這里使用 enumerate 方法適配一個迭代器來產(chǎn)生一個值和其在迭代器中的索引,他們位于一個元組中。第一個產(chǎn)生的值是元組 (0, 'a')。當(dāng)這個值匹配模式 (index, value),index 將會是 0 而 value 將會是 'a',并打印出第一行輸出。

let 語句

在本章之前,我們只明確的討論過通過 match 和 if let 使用模式,不過事實上也在別的地方使用過模式,包括 let 語句。例如,考慮一下這個直白的 let 變量賦值:

let x = 5;

本書進(jìn)行了不下百次這樣的操作,不過你可能沒有發(fā)覺,這正是在使用模式!let 語句更為正式的樣子如下:

let PATTERN = EXPRESSION;

像 let x = 5; 這樣的語句中變量名位于 PATTERN 位置,變量名不過是形式特別樸素的模式。我們將表達(dá)式與模式比較,并為任何找到的名稱賦值。所以例如 let x = 5; 的情況,x 是一個代表 “將匹配到的值綁定到變量 x” 的模式。同時因為名稱 x 是整個模式,這個模式實際上等于 “將任何值綁定到變量 x,不管值是什么”。

為了更清楚的理解 let 的模式匹配方面的內(nèi)容,考慮示例 18-4 中使用 let 和模式解構(gòu)一個元組:

    let (x, y, z) = (1, 2, 3);

示例 18-4: 使用模式解構(gòu)元組并一次創(chuàng)建三個變量

這里將一個元組與模式匹配。Rust 會比較值 (1, 2, 3) 與模式 (x, y, z) 并發(fā)現(xiàn)此值匹配這個模式。在這個例子中,將會把 1 綁定到 x,2 綁定到 y 并將 3 綁定到 z。你可以將這個元組模式看作是將三個獨立的變量模式結(jié)合在一起。

如果模式中元素的數(shù)量不匹配元組中元素的數(shù)量,則整個類型不匹配,并會得到一個編譯時錯誤。例如,示例 18-5 展示了嘗試用兩個變量解構(gòu)三個元素的元組,這是不行的:

    let (x, y) = (1, 2, 3);

示例 18-5: 一個錯誤的模式結(jié)構(gòu),其中變量的數(shù)量不符合元組中元素的數(shù)量

嘗試編譯這段代碼會給出如下類型錯誤:

$ cargo run
   Compiling patterns v0.1.0 (file:///projects/patterns)
error[E0308]: mismatched types
 --> src/main.rs:2:9
  |
2 |     let (x, y) = (1, 2, 3);
  |         ^^^^^^   --------- this expression has type `({integer}, {integer}, {integer})`
  |         |
  |         expected a tuple with 3 elements, found one with 2 elements
  |
  = note: expected tuple `({integer}, {integer}, {integer})`
             found tuple `(_, _)`

For more information about this error, try `rustc --explain E0308`.
error: could not compile `patterns` due to previous error

如果希望忽略元組中一個或多個值,也可以使用 _ 或 ..,如 “忽略模式中的值” 部分所示。如果問題是模式中有太多的變量,則解決方法是通過去掉變量使得變量數(shù)與元組中元素數(shù)相等。

函數(shù)參數(shù)

函數(shù)參數(shù)也可以是模式。列表 18-6 中的代碼聲明了一個叫做 foo 的函數(shù),它獲取一個 i32 類型的參數(shù) x,現(xiàn)在這看起來應(yīng)該很熟悉:

fn foo(x: i32) {
    // code goes here
}

列表 18-6: 在參數(shù)中使用模式的函數(shù)簽名

x 部分就是一個模式!類似于之前對 let 所做的,可以在函數(shù)參數(shù)中匹配元組。列表 18-7 將傳遞給函數(shù)的元組拆分為值:

文件名: src/main.rs

fn print_coordinates(&(x, y): &(i32, i32)) {
    println!("Current location: ({}, {})", x, y);
}

fn main() {
    let point = (3, 5);
    print_coordinates(&point);
}

列表 18-7: 一個在參數(shù)中解構(gòu)元組的函數(shù)

這會打印出 Current location: (3, 5)。值 &(3, 5) 會匹配模式 &(x, y),如此 x 得到了值 3,而 y得到了值 5。

因為如第十三章所講閉包類似于函數(shù),也可以在閉包參數(shù)列表中使用模式。

現(xiàn)在我們見過了很多使用模式的方式了,不過模式在每個使用它的地方并不以相同的方式工作;在一些地方,模式必須是 irrefutable 的,意味著他們必須匹配所提供的任何值。在另一些情況,他們則可以是 refutable 的。接下來讓我們討論這兩個概念。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號