Rust 模式匹配
Rust 有許多很好的特性,模式匹配就是其中之一。Rust 的模式匹配使代碼具有表現力、可讀性和清晰性。
基本模式
Rust 中的模式分爲兩種類型:條件匹配模式 (refutable) 和完全匹配模式(irrefutable)。使用哪一個取決於上下文。
1// Irrefutable patterns
2let x = 2;
3let (x, y) = (2, 3);
4
5// WILL NOT COMPILE
6// let does not allow refutable patterns
7let Ok(x) = someString.parse::<i32>()
8// trying to parse a string will return a Result, and can not guarantee that a result and not an Err is returned
let 語句是完全匹配模式,不允許條件匹配。而 if let 語句是條件匹配模式:
1if let Ok(x) = someString.parse::<i32>() {
2 // ... do something if someString can be parsed as a 32 bit integer ...
3}
4
5// if let can have a refutable pattern, so we can also use a value for x:
6if let Ok(64) = someString.parse::<i32>() {
7 // ... do something if someString can be parsed as a 32 bit integer ...
8}
下面我們將看到更多這類語句和模式的例子。
解構
許多模式匹配用於解構數據類型,它們也可以混合在一起進行模式匹配。
元組
1// myTuple is of type (i32, i32, &str)
2let my_tuple = (1, 2, "hellothere");
3let (x, y, my_str) = my_tuple;
在最後一行中,我們看到 my_tuple 被解構爲 3 個新變量: x、y 和 my_str。這可以用於所有類型的元組,只要析構類型匹配。
你也可以用..(可能是多個) 或_ (single),它們通常用於跳過元素:
1 // ignore my_str
2 let (x, y, _) = my_tuple;
3
4 // ignore everything after x
5 let (x, ..) = my_tuple;
6
7
8 // bigger tuple
9 let bigger_tuple = (1, 2, 3, 4, 5);
10
11 // get first and last
12 let (first, .., last) = bigger_tuple;
13
14 // ambiguous! NOT ALLOWED
15 // How would the compiler even know which element you wanted
16 let (.., middle, ..) = bigger_tuple;
Structs
1 // define a simple struct
2 struct Point {
3 x: f32,
4 y: f32,
5 z: f32
6 }
7
8 // create a variable to use
9 let myPoint = Point {
10 x: 1.0,
11 y: 0.5,
12 z: -1.0
13 };
14
15 // destructure it!
16 let Point { x, y, z} = my_point;
17
18 // Maybe we just want x and y?
19 let Point { x, y, .. } = my_point;
20
21 // or maybe just z
22 let Point { z, .. } = my_point;
在解構 struct 時應該注意的一件事是,名稱必須與 struct 中找到的名稱匹配,並且.. 必須放在最後,表示匹配其餘部分並忽略結果。
枚舉
枚舉最簡單的情況就是匹配一個沒有數據的枚舉:
1 // define a simple enum
2 enum Color {
3 Red,
4 Blue,
5 Green
6 }
7
8 // match if our color is green
9 if let Color::Green = my_color {
10 // .. do something is color is green ..
11 }
讓我們看一個包含數據的例子:
1 // More advanced enum
2 enum HttpRequest {
3 Get,
4 Post(String)
5 }
6
7 // match the post request
8 if let HttpRequest::Post(data) = my_request {
9 // .. do something with the post request data ...
10 }
11
12 // can also ignore data
13 if let HttpRequest::Post(_) = my_request {
14 // .. do something when post request ...
15 }
組合
你也可以將以上所有的類型組合成你自己的模式!枚舉中的 struct,元組中的枚舉等等。這樣的例子不勝枚舉!
1 // Define some nested structure
2 enum Color {
3 Red,
4 Blue,
5 Green
6 }
7
8 // imagine old OpenGL from the early 2000s where colors of points were interpolated across the shape
9 struct Point {
10 x: f32,
11 y: f32,
12 z: f32,
13 color: Color
14 }
15
16 struct Triangle(Point, Point, Point);
17
18
19 // A destructuring based upon the data we want
20 // gvet only x for the first point when the first points color is blue
21 if let Triangle(
22 Point {
23 x,
24 color: Color::Blue, ..
25 },
26 ..,
27 ) = my_triangle {
28 // .. do something with the data we wanted for some reason ..
29 }
其他模式
or-matcher
1 // matches 1, 2 or 3
2 1 | 2 | 3
3
4 // Matches one of the strings
5 "first" | "second"
範圍匹配
1 // matches 1 to 10 (inclusive)
2 1..=10
3
4 // matches 1 to 10 (non-inclusive)
5 1..10
範圍還可以用作數組的索引,以獲取多個元素。
函數簽名中的模式匹配
可以在函數定義中使用模式!這真的很酷,對吧?你必須記住,這些模式必須是完全匹配模式,就像 let。
1// test data
2struct Vector2d {
3 x: f32,
4 y: f32
5}
6
7// destructured Vector2d
8fn length(Vector2d { x, y }: Vector2d) -> f32 {
9 (x.powi(2) + y.powi(2)).sqrt()
10}
11
12fn x_val(Vector2d { x, .. }: Vector2d) -> f32 {
13 x
14}
本文翻譯自:
https://dev.to/themkat/the-awesomeness-of-pattern-matching-in-rust-3lbn
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/KYXDYxT4Cl_5l9Xaq2XvJw