什么是 Pattern Matching(模式匹配)
? 模式匹配就是一種“描述式”的寫法,不需要你手動判斷、提取數據,而是直接描述你希望的數據結構是什么樣子,系統自動判斷并提取。?
你給的定義拆解:
? Instead of explicitly extracting and testing…
傳統寫法是這樣的:
if (shape.type == "circle") {double r = shape.radius;// do something
} else if (shape.type == "rectangle") {double w = shape.width;double h = shape.height;// do something
}
這種方式需要你先判斷類型,再顯式地提取數據成員。這就是“explicitly extracting and testing”。
Pattern Matching 改寫為:
match shape {Circle(r) => { /* use r directly */ },Rectangle(w, h) => { /* use w and h directly */ },
}
你直接描述想要的結構,比如一個 Circle(r)
,系統就會幫你提取 r
,而不需要你去“訪問屬性”。
你也可以把它想象成這樣:
正則表達式 | 模式匹配 |
---|---|
匹配文本結構 | 匹配數據結構 |
提取子串 | 提取子字段 |
(\d+)-(\w+) | Rectangle(w, h) |
if (x matches pattern) | match x { pattern => ... } |
總結一句話
模式匹配 = 數據結構的“正則表達式”
它讓你聲明你想要的數據形狀,并在匹配時自動提取內容并處理。
這是一個 經典的 C++ switch-case
語句例子,它展示了 在運行時對整型變量 i
進行分支匹配的能力。下面是對這段代碼的逐行解釋:
原始代碼:
switch (i) {case 1:std::cout << "one";break;case 2:std::cout << "two";break;case 3:std::cout << "three";break;default:std::cout << "unknown";
}
代碼含義:
switch (i)
:根據變量i
的值,進入匹配的分支。case 1:
:如果i == 1
,輸出 “one”。case 2:
:如果i == 2
,輸出 “two”。case 3:
:如果i == 3
,輸出 “three”。default:
:如果不匹配任何case
,輸出 “unknown”。
特點:
特性 | 說明 |
---|---|
運行時匹配 | 編譯時無法確定分支走向,必須等 i 的值在運行時才知道。 |
整型值支持 | 傳統 switch 只支持 int 或 enum 類型。 |
手動 break | 每個分支后需要加 break 防止“貫穿執行”到下一個 case。 |
default 備選 | default 分支相當于“else”邏輯。 |
類比模式匹配(Pattern Matching)
switch
是一種最基礎的“模式匹配”形式,但功能非常有限:
特性 | switch | 模式匹配(如 Rust) |
---|---|---|
支持數據結構 | 僅支持整數值匹配 | 支持結構體/枚舉/元組等 |
自動提取字段 | 不能 | 自動解構(如 Point(x, y) ) |
表達式形式 | 語句形式,不能直接賦值 | 可作為表達式返回值 |
這段 Haskell 代碼是關于 模式匹配(Pattern Matching) 和 元組 / 列表的分解式函數定義,下面是對每一部分的詳細解釋和理解:
一、函數定義:提取三元組中的元素
first :: (a, b, c) -> a
first (x, _, _) = x
- 類型簽名
:: (a, b, c) -> a
表示:函數first
接收一個三元組(a, b, c)
,返回其中的第一個元素a
。 (x, _, _) = x
使用模式匹配提取第一個值,忽略其他兩個(用_
表示不關心)。
類似的:
second :: (a, b, c) -> b
second (_, y, _) = y
third :: (a, b, c) -> c
third (_, _, z) = z
這些函數從三元組中提取第二、第三個元素。
二、列表分析函數 describeList
describeList :: [a] -> String
describeList xs = "The list is " ++ case xs of[] -> "empty."[x] -> "a singleton list."xs -> "a longer list."
類型說明:
:: [a] -> String
表示該函數接收一個任意類型元素的列表,返回一個String
描述。
邏輯說明:
case xs of
使用 模式匹配 來分析xs
的結構:模式 匹配條件 返回文本 []
空列表 "empty."
[x]
只包含一個元素的列表 "a singleton list."
xs
(默認)多于一個元素的列表 "a longer list."
示例:
describeList [] -- "The list is empty."
describeList [42] -- "The list is a singleton list."
describeList [1,2,3] -- "The list is a longer list."
三、總結
概念 | 說明 |
---|---|
模式匹配(Pattern Matching) | Haskell 的核心特性,可在函數參數、case 表達式中直接分解數據結構。 |
元組分解 | (x, _, _) 形式表示從三元組中提取出想要的元素。 |
列表匹配 | [] , [x] , xs 等用于分別匹配空列表、單元素列表、多元素列表。 |
表達式匹配 + 拼接 | 使用 ++ 拼接字符串,用 case 對輸入做結構匹配判斷并產生不同返回值。 |
你給出的這段代碼是 Rust 中 模式匹配(match
) 的典型用法。下面是對它的完整解釋:
代碼回顧
let x = 1;
match x {1 | 2 => println!("one or two"), 3 => println!("three"),_ => println!("anything"),
}
逐行解釋
let x = 1;
- 這行代碼定義了一個變量
x
,它的值為1
。
match x { ... }
這是 Rust 中的 模式匹配結構,類似于其他語言中的 switch
,但更強大。
Rust 的 match
表達式根據變量的值與不同的 模式(patterns) 進行匹配,一旦匹配成功,就執行對應的代碼塊。
分支解釋:
1 | 2 => println!("one or two"),
1 | 2
表示:如果x
是 1 或 2,就執行這一分支。|
是邏輯“或”的模式匹配用法(不是布爾操作)。
3 => println!("three"),
- 當
x == 3
時匹配這個分支。
_ => println!("anything"),
_
是通配符,表示“其他任何情況”。- 如果
x
不是 1、2 或 3,就會匹配這個分支。
本例中運行結果
由于 x = 1
,因此匹配第一個分支:
one or two
總結
結構 | 說明 | |
---|---|---|
match | 用于模式匹配變量的值 | |
` | ` | 匹配多個值中的任一個 |
_ | 匹配所有未被顯式列出的情況 | |
=> | 分支體開始 |
小技巧
match
在 Rust 中是表達式(expression),所以它可以返回值。- 分支是窮盡性匹配,編譯器會強制你覆蓋所有可能性,或使用
_
兜底。 match
也可以解構結構體、枚舉、元組、引用等,功能非常強大。
這段 Rust 代碼展示了 模式匹配(pattern matching) 在元組(tuple)上的用法。我們來逐步理解它:
原始代碼
let tup = (1, 0);
match tup {(0, 0) => println!("both zero"),(x, 0) => println!("{} and zero", x),(0, y) => println!("zero and {}", y),_ => println!("did not match"),
}
變量定義
let tup = (1, 0);
- 創建了一個元組變量
tup
,其值是(1, 0)
。
match
分支解析
Rust 的 match
會從上到下嘗試匹配每個模式:
① (0, 0) => println!("both zero")
- 匹配元組兩個元素都是 0 的情況。
- 當前是
(1, 0)
,不匹配。
② (x, 0) => println!("{} and zero", x)
- 匹配元組第二個元素為
0
,第一個元素任意(綁定為x
)。 - 當前是
(1, 0)
,匹配成功。 - 執行:
println!("{} and zero", x)
,輸出:
1 and zero
匹配成功后,match
結構結束,不會繼續匹配下面的分支。
③ (0, y) => println!("zero and {}", y)
- 匹配第一個是 0,第二個任意的元組。
- 當前不匹配,因此不會執行。
④ _ => println!("did not match")
_
是通配符:匹配所有未匹配到的情況。- 本例中沒走到這一分支。
運行結果
1 and zero
小結
模式 | 含義 | 匹配 (1, 0) 嗎? |
---|---|---|
(0, 0) | 兩個都是 0 | 否 |
(x, 0) | 第二個是 0,第一個綁定為 x | 是 |
(0, y) | 第一個是 0,第二個綁定為 y | 否 |
_ | 其他任何情況(兜底) | 不會執行 |
如果你想學習更多 Rust 中的模式匹配技巧,例如: |
- 匹配結構體和枚舉
- 使用
match guard
(例如if x > 0
) - 模式綁定的細節(如
@
綁定)
這段 Rust 代碼展示了如何使用 枚舉(enum
)和模式匹配(match
) 來處理不同類型的消息(Message
)。我們來逐步分析和理解它:
枚舉定義
enum Message {Quit,ChangeColor(i32, i32, i32),Move { x: i32, y: i32 },Write(String),
}
這定義了一個 Message
類型,它有 4 種變體(variants):
變體名 | 類型 | 描述 |
---|---|---|
Quit | 無數據 | 退出指令 |
ChangeColor | 包含三個 i32 參數 | 改變顏色(RGB) |
Move | 是一個具名結構體樣式的變體 | 移動到 (x, y) 坐標位置 |
Write | 包含一個 String | 輸出字符串 |
process_message
函數
fn process_message(msg: Message) {match msg {Message::Quit => quit(),Message::ChangeColor(r, g, b) => change_color(r, g, b),Message::Move { x: x, y: y } => move_cursor(x, y),Message::Write(s) => println!("{}", s),};
}
該函數接收一個 Message
類型的參數,然后使用 match
匹配它是哪種變體,并執行相應的操作。
逐個分支解釋
1. Message::Quit => quit()
- 如果是
Quit
變體,調用quit()
函數。 - 不包含任何數據。
2. Message::ChangeColor(r, g, b) => change_color(r, g, b)
- 如果是
ChangeColor
,提取出三個整數,綁定為r, g, b
,然后傳給change_color
函數。 - 這是 位置匹配(positional matching)。
3. Message::Move { x: x, y: y } => move_cursor(x, y)
- 如果是
Move
變體,它是具名字段結構體形式。 - 提取
x
和y
字段,傳入move_cursor(x, y)
。 - 可以簡寫為
{ x, y }
而不是{ x: x, y: y }
。
4. Message::Write(s) => println!("{}", s)
- 如果是
Write(String)
,提取出字符串s
,并打印。
簡寫優化(推薦寫法)
你可以把 x: x, y: y
簡寫為 x, y
:
Message::Move { x, y } => move_cursor(x, y)
示例調用
process_message(Message::Quit);
process_message(Message::Write("Hello!".to_string()));
process_message(Message::Move { x: 10, y: 20 });
process_message(Message::ChangeColor(255, 0, 0));
小結
這個例子體現了 Rust 的模式匹配能力:
- 適用于結構體、枚舉、元組等
- 自動解構并綁定變量
- 簡潔且類型安全
如果你來自其他語言(如 C++、Java),可以把這理解為: enum
是 tagged union + 類型安全match
類似switch
,但更強大,可解構結構體和元組
后面應該是介紹這個c++怎么實現的看不懂 知道模式匹配這個東西就行
https://github.com/jbandela/simple_match