CppCon 2015 學習:Simple, Extensible Pattern Matching in C++14

什么是 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 只支持 intenum 類型。
手動 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 變體,它是具名字段結構體形式。
  • 提取 xy 字段,傳入 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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/84220.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/84220.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/84220.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

刷題記錄(7)二叉樹

一、單值二叉樹 二叉樹為二叉鏈表形式&#xff0c;結點為&#xff1a; 大概看看題就知道這道題讓我們判斷一個樹到底所有結點的值是不是相同&#xff0c;相同就是單值二叉樹。在實現二叉樹相關操作的時候已經體會到了&#xff0c;遞歸來遍歷二叉樹是非常舒服的&#xff08;做這…

開源:FTP同步工具

文章目錄 簡介功能特性Windows (EXE)從源代碼構建依賴項Linux 構建Windows 構建 使用方法軟件截圖主界面FTP 設置快捷菜單定時設置 配置說明開發與貢獻許可證 歡迎來到盹貓的博客 本篇文章主要介紹了 [開源:FTP同步工具] ?博主廣交技術好友&#xff0c;喜歡我的文章的可以關注…

視頻質量測試點

目錄 功能/UI 端側性能 媒體質量 主觀 客觀 穩定性 兼容性 功能/UI 視頻預覽音頻預覽音視頻同步全屏收藏打賞 端側性能 PC端&#xff1a;內存占用、網絡帶寬占用等&#xff1b; 移動端&#xff1a;內存占用、功耗、發熱、流量消耗等&#xff1b; 媒體質量 主觀 音…

Ray框架:分布式AI訓練與調參實踐

Ray框架&#xff1a;分布式AI訓練與調參實踐 系統化學習人工智能網站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目錄 Ray框架&#xff1a;分布式AI訓練與調參實踐摘要引言框架架構解析1. 核心組件設計2. 關鍵技術實現2.1 動態資源調度2.2 …

成都鼎訊硬核科技!雷達目標與干擾模擬器,以卓越性能制勝電磁頻譜戰

在現代戰爭中&#xff0c;電磁頻譜已成為繼陸、海、空、天之后的 “第五維戰場”&#xff0c;雷達作為電磁頻譜領域的關鍵裝備&#xff0c;其干擾與抗干擾能力的較量&#xff0c;直接影響著戰爭的勝負走向。由成都鼎訊科技匠心打造的雷達目標與干擾模擬器&#xff0c;憑借數字射…

ubuntu22.04 安裝docker 和docker-compose

首先你要確保沒有docker環境或者使用命令刪掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安裝docker 更新軟件環境 sudo apt update sudo apt upgrade下載docker依賴和GPG 密鑰 # 依賴 apt-get install ca-certificates curl gnupg lsb-rel…

2025 后端自學UNIAPP【項目實戰:旅游項目】6、我的收藏頁面

代碼框架視圖 1、先添加一個獲取收藏景點的列表請求 【在文件my_api.js文件中添加】 // 引入公共的請求封裝 import http from ./my_http.js// 登錄接口&#xff08;適配服務端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…

20250609在榮品的PRO-RK3566開發板的Android13下解決串口可以執行命令但是腳本執行命令異常的問題

20250609在榮品的PRO-RK3566開發板的Android13下解決串口可以執行命令但是腳本執行命令異常的問題 2025/6/9 20:54 緣起&#xff0c;為了跨網段推流&#xff0c;千辛萬苦配置好了網絡參數。 但是命令iptables -t filter -F tetherctrl_FORWARD可以在調試串口/DEBUG口正確執行。…

【C/C++】高效的位操作

位運算&#xff08;Bitwise Operation&#xff09;是直接對整數的二進制位進行操作的運算方式&#xff0c;在底層開發、性能優化、算法設計中廣泛使用。 1 基本位運算符及含義 運算符名稱示例&#xff08;a5, b3&#xff09;運算過程&#xff08;二進制&#xff09;結果&按…

后端下載限速(redis記錄實時并發,bucket4j動態限速)

? 使用 Redis 記錄 所有用戶的實時并發下載數? 使用 Bucket4j 實現 全局下載速率限制&#xff08;動態&#xff09;? 支持 動態調整限速策略? 下載接口安全、穩定、可監控 &#x1f9e9; 整體架構概覽 模塊功能Redis存儲全局并發數和帶寬令牌桶狀態Bucket4j Redis分布式限…

android app 一個 crash的解決過程!

一、日志&#xff1a; crash 2024-10-25 12:15:33.020 2113-2113 AndroidRuntime pid-2113 E FATAL EXCEPTION: main Process: com..workhome, PID: 2113 java.lang.RuntimeException: Unable to start activity ComponentInfo{com..w…

[Java 基礎]Object 類

java.lang.Object 是 Java 所有類的直接或間接父類&#xff0c;Java 中每個類都默認繼承 Object 類&#xff08;即使你沒寫 extends Object&#xff09;。 Object 中的常用方法&#xff1a; 方法名功能簡介toString()返回對象的字符串表示equals(Object)判斷兩個對象是否“邏…

大數據學習(135)-Linux系統性指令

&#x1f34b;&#x1f34b;大數據學習&#x1f34b;&#x1f34b; &#x1f525;系列專欄&#xff1a; &#x1f451;哲學語錄: 用力所能及&#xff0c;改變世界。 &#x1f496;如果覺得博主的文章還不錯的話&#xff0c;請點贊&#x1f44d;收藏??留言&#x1f4dd;支持一…

【Fifty Project - D35】

今日完成記錄 TimePlan完成情況7&#xff1a;00 - 7&#xff1a;40爬坡√8&#xff1a;30 - 11&#xff1a;30Rabbit MQ√17&#xff1a;30 - 18&#xff1a;30羽毛球√ RabbitMQ 消費者端如何保證可靠性&#xff1f; 消息投遞過程出現網絡故障消費者接收到消息但是突然宕機…

P3 QT項目----記事本(3.4)

3.4 文件選擇對話框 QFileDialog 3.4.1 QFileDialog 開發流程 使用 QFileDialog 的基本步驟通常如下&#xff1a; 實例化 &#xff1a;首先&#xff0c;創建一個 QFileDialog 對象的實例。 QFileDialog qFileDialog;設置模式 &#xff1a;根據需要設置對話框的模式&…

學習筆記(26):線性代數-張量的降維求和,簡單示例

學習筆記(26)&#xff1a;線性代數-張量的降維求和&#xff0c;簡單示例 1.先理解 “軸&#xff08;Axis&#xff09;” 的含義 張量的 “軸” 可以理解為 維度的方向索引 。對于形狀為 (2, 3, 4) 的張量&#xff0c;3 個軸的含義是&#xff1a; 軸 0&#xff08;axis0&…

健康檔案實訓室:構建全周期健康管理的數據基石

一、健康檔案實訓室建設背景 隨著“健康中國2030”戰略深入推進&#xff0c;健康檔案作為居民健康數據的核心載體&#xff0c;在疾病預防、慢性病管理、醫療決策等領域的價值日益凸顯。在此背景下&#xff0c;健康檔案實訓室建設成為職業院校對接政策要求、培養專業健康管理…

【MATLAB第119期】基于MATLAB的KRR多輸入多輸出全局敏感性分析模型運用(無目標函數,考慮代理模型)

【MATLAB第119期】基于MATLAB的KRR多輸入多輸出全局敏感性分析模型運用&#xff08;無目標函數&#xff0c;考慮代理模型&#xff09; 下一期研究SHAP的多輸入多輸出敏感性分析方法 一、SOBOL&#xff08;無目標函數&#xff09; &#xff08;1&#xff09;針對簡單線性數據…

Linux常用文件目錄命令

瀏覽目錄命令&#xff1a; ls 、pwd目錄操作命令&#xff1a;cd、mkdir、rmdir瀏覽文件命令&#xff1a;cat、more、less、head、tail文件操作命令&#xff1a;cp、rm、mv、find、grep、tar 瀏覽目錄命令 ls ? 命令名稱&#xff1a;ls ? 命令英文原意&#xff1a;list ? …

PIN碼vs密碼,電腦登錄的快捷鍵你用對了嗎?

你是否也遇到過這樣的窘境&#xff1a;信心滿滿地輸入電腦開機密碼&#xff0c;屏幕卻無情地提示“密碼錯誤”。仔細一看&#xff0c;才發現登錄界面悄悄地變成了要求輸入“PIN碼”。這種因為混淆了PIN碼和賬戶密碼而導致的開機失敗&#xff0c;相信不少朋友都碰到過。 PIN碼作…