前言
本系列文書寫我個人初探 Rust 的學習筆記,章節劃分主要基於著名的 The Book,The Rust Programming Language,程式碼部分通常是個人閱讀消化後以方便說明的方式撰寫,完整學習建議直接參見該書。
The Rust Programming Language
該書也有中文翻譯版,不過個人閱讀以英文原版為主以鞏固對 terminology 的一致認識,我認為對未來閱讀以及查找資料會較為順暢。
不論語言該書都是相當優秀的學習資源,選擇適合你的語言開始學習 Rust 吧。
Appendix F: Translations of the Book
列舉 Enums
enum 定義的是可能的一組特定數值,以下定義一組顏色。
enum Color {
Green,
Red,
Blue
}
struct Tag {
name: String,
color: Color
}
使用時則是使用 :: 來取得特定顏色。
let tag1 = Tag {
name: String::from("new"),
color: Color::Blue
};
enum 中的 variants 也能夠擁有數值,以下讓 Color 都能有擁有一個 String。
enum Color {
Green(String),
Red(String),
Blue(String)
}
fn main() {
let c1 = Color::Blue(String::from("Blue"));
}
這種做法可以讓 enum 中不同的 variant 有不同的值。
enum Color {
Green(String),
Red(i32),
Blue(f64)
}
fn main() {
let c1 = Color::Green(String::from("Blue"));
let c2 = Color::Red(5);
let c3 = Color::Blue(1.0);
}
enum 像 struct 一樣可以有 impl block 定義 methods。
#[derive(Debug)]
enum Color {
Green(String),
Red(String),
Blue(String)
}
impl Color {
fn print(&self) {
println!("{:?}", self)
}
}
fn main() {
let c1 = Color::Blue(String::from("Blue"));
c1.print(); // Blue("Blue")
}
Option
Option 是一種內建在 Rust 的 standard library 的 enum,他是 Rust 處理值可能為空值的解決方案,因為 Rust 不像其他許多語言有空值的型別,如 Javascript 的 null 或 undefined。
以下是 Option 的定義:
enum Option<T> {
None,
Some(T),
}
看起來非常的 self explained,Option 代表的是可能為空 None、或可能有某些數值 Some(T)。這邊的 T 是 generic,也就是泛型,之後會學習到。
Result
還有另一種特定的 enum 叫做 Result,與 Option 有些類似,這是他的定義:
enum Result<T, E> {
Ok(T),
Err(E),
}
在某些可能會失敗的函式中會使用 Result 作為回傳值 (比如讀取檔案),讓我們 handle success 和 error case。
模式配對 Pattern matching
Pattern matching 是讓 Rust 的 enum 真正強大的地方,它是一種流程控制,有點像其他語言中的 switch case。
下面的程式是一個簡短的 pattern matching 的範例,我們使用 match 進行 pattern matching,為每個 variant 配對一段 expression,l 在進入 match 之後比對各個 variant 然後執行配對到的程式。
enum Language {
Chinese,
English,
Japanese
}
fn main() {
let l = Language::Japanese;
match l {
Language::Chinese => println!("你好"),
Language::English => println!("Hello"),
Language::Japanese => println!("こんにちは")
};
// output: こんにちは
}
當 enum 有綁定值時可以使用以下方式取得值。
enum Language {
Chinese(String),
English(String),
Japanese(String)
}
fn main() {
let l = Language::English(String::from("Josh"));
match l {
Language::Chinese(s) => println!("你好 {}", s),
Language::English(s) => println!("Hello {}", s),
Language::Japanese(s) => println!("こんにちは {}", s)
};
// output: Hello Josh
}
pattern matching 必須涵蓋所有可能的 variant,若有缺少會直接報錯。
enum Language {
Chinese(String),
English(String),
Japanese(String)
}
fn main() {
let l = Language::English(String::from("Josh"));
match l {
Language::Chinese(s) => println!("你好 {}", s),
Language::English(s) => println!("Hello {}", s),
};
// ERROR: non-exhaustive patterns: `Language::Japanese(_)` not covered
}
如果只關心部分的可能性,又不想把全部列出來,可以使用 other 變數做 catch-all 的操作。
#[derive(Debug)]
enum Language {
Chinese(String),
English(String),
Japanese(String)
}
fn main() {
let l = Language::English(String::from("Josh"));
match l {
Language::Chinese(s) => println!("你好 {}", s),
other => println!("{:?}", other)
};
// output: English("Josh")
}
如果也不需要取得變數,可以用 _ 替代 other。
enum Language {
Chinese(String),
English(String),
Japanese(String)
}
fn main() {
let l = Language::English(String::from("Josh"));
match l {
Language::Chinese(s) => println!("你好 {}", s),
_ => println!("Hello")
};
}
甚至如果只關心部分的可能而其他想要直接忽略,可以用空的 tuple (),這樣就什麼都不會發生。
enum Language {
Chinese(String),
English(String),
Japanese(String)
}
fn main() {
let l = Language::English(String::from("Josh"));
match l {
Language::Chinese(s) => println!("你好 {}", s),
_ => ()
};
}
像上面這種情況可以用 if let 語法做更精簡的改寫。
if let
當我們只關心其中一種情況,其他所有情況都想忽略時,if let 語法提供了更簡單的寫法。
enum Language {
Chinese(String),
English(String),
Japanese(String)
}
fn main() {
let l = Language::English(String::from("Josh"));
if let Language::English(s) = l {
println!("Hello {}", s);
}
// output: Hello Josh
}
就像單純的 if 一樣,if let 也可以加上 else 區塊,就相當於 pattern matching 中 _ 的區塊。
enum Language {
Chinese(String),
English(String),
Japanese(String)
}
fn main() {
let l = Language::Chinese(String::from("Josh"));
if let Language::English(s) = l {
println!("Hello {}", s);
} else {
println!("Hello world!");
}
// // output: Hello world!
}
寫在最後
The book 中下一章是關於套件管理、程式碼拆分與管理專案結構,這部分很重要不過我習慣在實戰中慢慢邊參考邊練習,這邊稍微去閱讀就好,筆記會跳過這章下一篇直接進入集合。