欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Rust 枚舉和模式匹配的實現(xiàn)

 更新時間:2023年12月07日 09:50:14   作者:和你一起去月球  
枚舉是 Rust 中非常重要的復合類型,也是最強大的復合類型之一,廣泛用于屬性配置、錯誤處理、分支流程、類型聚合等場景中,本文就來介紹一下Rust 枚舉和模式匹配,感興趣的可以了解一下

1、枚舉的定義

枚舉(enumerations),也被稱作 enums。枚舉允許你通過列舉可能的 成員(variants)來定義一個類型。首先,我們會定義并使用一個枚舉來展示它是如何連同數(shù)據(jù)一起編碼信息的。接下來,我們會探索一個特別有用的枚舉,叫做 Option,它代表一個值要么是某個值要么什么都不是。然后會講到在 match 表達式中用模式匹配,針對不同的枚舉值編寫相應要執(zhí)行的代碼。最后會介紹 if let,另一個簡潔方便處理代碼中枚舉的結(jié)構(gòu)。

下面看下下面這個示例:

#[derive(Debug)]
enum Sex {
    Man,
    Woman,
}
fn main() {
    let var = Sex::Man;
    println!("value is {:?}", var)
}

從上面代碼示例中,我們把性別可以枚舉出來,引用枚舉類型的某一個值的時候,可以通過枚舉名后面加一堆冒號來引用枚舉中的某一個屬性值。

下面這個例子,我們可以在枚舉中,它的成員可以有多種類型:

enum op {
    name(String),
    time(i32),
    People { name: String, age: i32 },
}

有關(guān)聯(lián)值的枚舉的方式和定義多個不同類型的結(jié)構(gòu)體的方式很相像,除了枚舉不使用 struct 關(guān)鍵字以及其所有成員都被組合在一起。

結(jié)構(gòu)體和枚舉還有另一個相似點:就像可以使用 impl 來為結(jié)構(gòu)體定義方法那樣,也可以在枚舉上定義方法。

    enum Op {
        Name(String),
        Time(i32),
        People { name: String, age: i32 },
    }

    impl Op {
        fn say(&self) {}
    }

讓我們看看標準庫中的另一個非常常見且實用的枚舉:Option。

1.1 Option 枚舉和其相對于空值的優(yōu)勢

這一部分會分析一個 Option 的案例,Option 是標準庫定義的另一個枚舉。Option 類型應用廣泛因為它編碼了一個非常普遍的場景,即一個值要么有值要么沒值。

例如,如果請求一個非空列表的第一項,會得到一個值,如果請求一個空的列表,就什么也不會得到。從類型系統(tǒng)的角度來表達這個概念就意味著編譯器需要檢查是否處理了所有應該處理的情況,這樣就可以避免在其他編程語言中非常常見的 bug。

編程語言的設(shè)計經(jīng)常要考慮包含哪些功能,但考慮排除哪些功能也很重要。Rust 并沒有很多其他語言中有的空值功能。空值(Null )是一個值,它代表沒有值。在有空值的語言中,變量總是這兩種狀態(tài)之一:空值和非空值。

然而,空值嘗試表達的概念仍然是有意義的:空值是一個因為某種原因目前無效或缺失的值。

問題不在于概念而在于具體的實現(xiàn)。為此,Rust 并沒有空值,不過它確實擁有一個可以編碼存在或不存在概念的枚舉。這個枚舉是 Option<T>,而且它定義于標準庫中,如下:

fn main() {
    enum Option<T> {
        None,
        Some(T),
    }
}

Option<T> 也仍是常規(guī)的枚舉,Some(T) 和 None 仍是 Option<T> 的成員。<T> 語法是一個我們還未講到的 Rust 功能。它是一個泛型類型參數(shù),所以你需要知道的就是 <T> 意味著 Option 枚舉的 Some 成員可以包含任意類型的數(shù)據(jù),同時每一個用于 T 位置的具體類型使得 Option<T> 整體作為不同的類型。這里是一些包含數(shù)字類型和字符串類型 Option 值的例子:

 enum Option<T> {
        None,
        Some(T),
    }
 let some_number = Some(5000);
 let some_char = Some('e');
 let some_boolean = Some(true);

讓我們再看一下如下示例,定義如下2個值進行相加會怎么樣?

fn main() {
    enum Option<T> {
        None,
        Some(T),
    }
    let some_number: i8 = 5;

    let absent_number: Option<i8> = Some(5);

    let plus = some_number + absent_number;
}

運行結(jié)果如下所示:

在這里有2個嚴重的問題:

第一個問題是let absent_number: Option<i8> = Some(5); 在這里賦值的時候會報錯,這2個類型名看起來很像,但實際上是不同的類型,無法進行賦值操作。

第二個是不同類型進行相加的時候,當在 Rust 中擁有一個像 i8 這樣類型的值時,編譯器確保它總是有一個有效的值。我們可以自信使用而無需做空值檢查。只有當使用 Option<i8>(或者任何用到的類型)的時候需要擔心可能沒有值,而編譯器會確保我們在使用值之前處理了為空的情況。

 2、match 控制流結(jié)構(gòu)

Rust 有一個叫做 match 的極為強大的控制流運算符,它允許我們將一個值與一系列的模式相比較,并根據(jù)相匹配的模式執(zhí)行相應代碼。模式可由字面值、變量、通配符和許多其他內(nèi)容構(gòu)成;

我們看一下如下示例,能夠更清楚的明白match的作用:

fn main() {
    enum Coin {
        Penny,
        Nickel,
        Dime,
        Quarter,
    }

    fn value_in_cents(coin: Coin) -> u8 {
        match coin {
            Coin::Penny => 1,
            Coin::Nickel => 5,
            Coin::Dime => 10,
            Coin::Quarter => 25,
        }
    }
    let res = value_in_cents(Coin::Nickel);
    print!("result {}", res)  // result 5
}

match 的作用,其他跟其他語言(例如,JavaScript)中的switch差不多,以上代碼中,方法接收了一個枚舉類型,match根據(jù)枚舉類型的不同成員來返回的不同的值,類似不同的分支,符合條件的分支,才會被最后返回,如果匹配到了某一個分支,想在執(zhí)行其他邏輯的時候,可以加一對花括號,在里面寫對應的邏輯即可。

    fn value_in_cents(coin: Coin) -> u8 {
        match coin {
            Coin::Penny => {
                print!("res: 執(zhí)行到這了");
                1
            }
            Coin::Nickel => 5,
            Coin::Dime => 10,
            Coin::Quarter => 25,
        }
    }

2.1 匹配 Option<T>

下面編寫一個函數(shù),它獲取一個 Option<i32> ,如果其中含有一個值,將其加一。如果其中沒有值,函數(shù)應該返回 None 值。

fn plus_one(x: Option<i32>) -> Option<i32> {
        match x {
            None => None,
            Some(i) => Some(i + 1),
        }
    }

    let five = Some(5);
    let six = plus_one(five);
    let none = plus_one(None);
    println!("{:?}  {:?}   {:?}", five, six, none)  // Some(5)  Some(6)   None

2.2 匹配是窮盡的

match 還有另一方面需要討論:這些分支必須覆蓋了所有的可能性。否則不能進行編譯。

fn plus_one(x: Option<i32>) -> Option<i32> {
        match x {
            Some(i) => Some(i + 1),
        }
    }

根據(jù)上面錯誤提示,我們知道Rust中match匹配必須是窮盡的,否則無法編譯通過。

2.3 通配模式和 _ 占位符

我們看一下如下示例:

fn main() {
    let dice_roll = 9;
    match dice_roll {
        3 => 3,
        7 => 7,
        hello => 9,
    };
}

3和7會匹配對應的值,定義一個變量例如:hello,則可以匹配其他任意情況下的值。

即使我們沒有列出 u8 所有可能的值,這段代碼依然能夠編譯,因為最后一個模式將匹配所有未被特殊列出的值。這種通配模式滿足了 match 必須被窮盡的要求。請注意,我們必須將通配分支放在最后,因為模式是按順序匹配的。如果我們在通配分支后添加其他分支,Rust 將會警告我們,因為此后的分支永遠不會被匹配到。

Rust 還提供了一個模式,當我們不想使用通配模式獲取的值時,請使用 _ ,這是一個特殊的模式,可以匹配任意值而不綁定到該值。這告訴 Rust 我們不會使用這個值,所以 Rust 也不會警告我們存在未使用的變量。

fn main() {
    let dice_roll = 9;
    match dice_roll {
        3 => 3,
        7 => 7,
        _ => 9,
    };
}

當我們匹配到其他情況,這種情況下我們不想運行任何代碼。可以返回一個空元組,如下所示:

fn main() {
    let dice_roll = 9;

    match dice_roll {
        3 => three(),
        7 => seven(),
        _ => (),
    }
    fn three() {}
    fn seven() {}
}

3、if let 簡潔控制流

我們先看一個示例:

fn main() {
    let config_max = Some(3u8);
    match config_max {
        Some(max) => println!("The maximum is configured to be {}", max),
        _ => (),
    }
}

如果值是 Some,我們希望打印出 Some 成員中的值,這個值被綁定到模式中的 max 變量里。對于 None 值我們不希望做任何操作。為了滿足 match 表達式(窮盡性)的要求,必須在處理完這唯一的成員后加上 _ => (),這樣也要增加很多煩人的樣板代碼。

為了簡化代碼,可以使用if let 來簡化一下:

fn main() {
    let config_max = Some(3u8);
    if let Some(max) = config_max {
        println!("res {}", max)
    }
}

使用 if let 意味著編寫更少代碼,更少的縮進和更少的樣板代碼。然而,這樣會失去 match 強制要求的窮盡性檢查。match 和 if let 之間的選擇依賴特定的環(huán)境以及增加簡潔度和失去窮盡性檢查的權(quán)衡取舍。

換句話說,可以認為 if let 是 match 的一個語法糖,它當值匹配某一模式時執(zhí)行代碼而忽略所有其他值。

至于下環(huán)線匹配的模式,可以通過if let else 來實現(xiàn),如下所示:

fn main() {
    let mut count = 0;
    let config_max = Some(3u8);
    if let Some(max) = config_max {
        println!("res {}", max)
    } else {
        count += 1;
    }
}

到此這篇關(guān)于Rust 枚舉和模式匹配的實現(xiàn)的文章就介紹到這了,更多相關(guān)Rust 枚舉和模式匹配內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • rust 如何使用 cargo-nextest 替代 cargo test

    rust 如何使用 cargo-nextest 替代 cargo te

    cargo-nextest 是新一代的rust測試程序,能夠極大提升測試性能,可以完全替代 cargo test 命令,這篇文章主要介紹了rust 如何使用 cargo-nextest 替代 cargo test,需要的朋友可以參考下
    2024-05-05
  • Rust 枚舉和模式匹配的實現(xiàn)

    Rust 枚舉和模式匹配的實現(xiàn)

    枚舉是 Rust 中非常重要的復合類型,也是最強大的復合類型之一,廣泛用于屬性配置、錯誤處理、分支流程、類型聚合等場景中,本文就來介紹一下Rust 枚舉和模式匹配,感興趣的可以了解一下
    2023-12-12
  • 使用systemd部署r-nacos的操作方法

    使用systemd部署r-nacos的操作方法

    r-nacos是一個用rust實現(xiàn)的nacos服務,我們用它平替java?nacos以降低服務占用內(nèi)存,提升服務的穩(wěn)定性,這篇文章主要介紹了使用systemd部署r-nacos,需要的朋友可以參考下
    2024-03-03
  • Rust for循環(huán)語法糖背后的API場景分析

    Rust for循環(huán)語法糖背后的API場景分析

    for語句是一種能確定循環(huán)次數(shù)的循環(huán),for 語句用于執(zhí)行代碼塊指定的次數(shù),今天通過本文給大家介紹Rust for循環(huán)語法糖背后的API場景分析,感興趣的朋友跟隨小編一起看看吧
    2022-11-11
  • rust將bitmap位圖文件另存為png格式的方法

    rust將bitmap位圖文件另存為png格式的方法

    通過添加依賴,轉(zhuǎn)換函數(shù)和單元測試操作步驟來解決將bitmap位圖文件另存為png格式文件,本文通過實例代碼給大家介紹的非常詳細,對rust bitmap位另存為png格式的操作方法感興趣的朋友一起看看吧
    2024-03-03
  • Rust 累計時間長度的操作方法

    Rust 累計時間長度的操作方法

    在Rust中,如果你想要記錄累計時間,通??梢允褂脴藴蕩熘械膕td::time::Duration類型,這篇文章主要介紹了Rust如何累計時間長度,需要的朋友可以參考下
    2024-05-05
  • Rust指南之生命周期機制詳解

    Rust指南之生命周期機制詳解

    Rust?生命周期機制是與所有權(quán)機制同等重要的資源管理機制,之所以引入這個概念主要是應對復雜類型系統(tǒng)中資源管理的問題,這篇文章主要介紹了Rust指南之生命周期機制詳解,需要的朋友可以參考下
    2022-10-10
  • 詳解Rust中的變量與常量

    詳解Rust中的變量與常量

    大多數(shù)嘗試過 Rust 的人都希望繼續(xù)使用它。但是如果你沒有使用過它,你可能會想——什么是 Rust,如何理解Rust中的變量與常量,感興趣的朋友跟隨小編一起看看吧
    2022-10-10
  • Rust語言的新手了解和學習入門啟蒙教程

    Rust語言的新手了解和學習入門啟蒙教程

    這篇文章主要介紹了rust的特點、安裝、項目結(jié)構(gòu)、IDE環(huán)境配置、代碼運行,講解了如何安裝Rust編譯器,創(chuàng)建和運行第一個Rust程序,并對Rust語言的特點和優(yōu)勢作了說明,包括內(nèi)存安全、高效性能、并發(fā)性、社區(qū)支持和統(tǒng)一包管理等,是新手了解和學習Rust語言的啟蒙教程
    2024-12-12
  • Rust語言之trait中的個方法可以重寫嗎

    Rust語言之trait中的個方法可以重寫嗎

    在Rust中,trait定義了一組方法,這些方法可以被一個或多個類型實現(xiàn),當你為某個類型實現(xiàn)一個trait時,你可以為該trait中的每個方法提供自己的具體實現(xiàn),本文將給大家介紹一下trait中的個方法是否可以重寫,需要的朋友可以參考下
    2023-10-10

最新評論