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 只支持 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
相关文章:
CppCon 2015 学习:Simple, Extensible Pattern Matching in C++14
什么是 Pattern Matching(模式匹配) ❝ 模式匹配就是一种“描述式”的写法,不需要你手动判断、提取数据,而是直接描述你希望的数据结构是什么样子,系统自动判断并提取。❞ 你给的定义拆解: ✴ Instead of …...

智警杯备赛--excel模块
数据透视与图表制作 创建步骤 创建 1.在Excel的插入或者数据标签页下找到数据透视表的按钮 2.将数据放进“请选择单元格区域“中,点击确定 这是最终结果,但是由于环境启不了,这里用的是自己的excel,真实的环境中的excel根据实训…...
uniapp获取当前位置和经纬度信息
1.1. 获取当前位置和经纬度信息(需要配置高的SDK) 调用uni-app官方API中的uni.chooseLocation(),即打开地图选择位置。 <button click"getAddress">获取定位</button> const getAddress () > {uni.chooseLocatio…...

【多线程初阶】单例模式 指令重排序问题
文章目录 1.单例模式1)饿汉模式2)懒汉模式①.单线程版本②.多线程版本 2.分析单例模式里的线程安全问题1)饿汉模式2)懒汉模式懒汉模式是如何出现线程安全问题的 3.解决问题进一步优化加锁导致的执行效率优化预防内存可见性问题 4.解决指令重排序问题 1.单例模式 单例模式确保某…...

基于Python的气象数据分析及可视化研究
目录 一.🦁前言二.🦁开源代码与组件使用情况说明三.🦁核心功能1. ✅算法设计2. ✅PyEcharts库3. ✅Flask框架4. ✅爬虫5. ✅部署项目 四.🦁演示效果1. 管理员模块1.1 用户管理 2. 用户模块2.1 登录系统2.2 查看实时数据2.3 查看天…...

Pandas 可视化集成:数据科学家的高效绘图指南
为什么选择 Pandas 进行数据可视化? 在数据科学和分析领域,可视化是理解数据、发现模式和传达见解的关键步骤。Python 生态系统提供了多种可视化工具,如 Matplotlib、Seaborn、Plotly 等,但 Pandas 内置的可视化功能因其与数据结…...

新版NANO下载烧录过程
一、序言 搭建 Jetson 系列产品烧录系统的环境需要在电脑主机上安装 Ubuntu 系统。此处使用 18.04 LTS。 二、环境搭建 1、安装库 $ sudo apt-get install qemu-user-static$ sudo apt-get install python 搭建环境的过程需要这个应用库来将某些 NVIDIA 软件组件安装到 Je…...
Vue 实例的数据对象详解
Vue 实例的数据对象详解 在 Vue 中,数据对象是响应式系统的核心,也是组件状态的载体。理解数据对象的原理和使用方式是成为 Vue 专家的关键一步。我将从多个维度深入剖析 Vue 实例的数据对象。 一、数据对象的定义方式 1. Options API 中的定义 在 Options API 中,使用 …...

Axure Rp 11 安装、汉化、授权
Axure Rp 11 安装、汉化、授权 1、前言2、汉化2.1、汉化文件下载2.2、windows汉化流程2.3、 macOs汉化流程 3、授权 1、前言 Axure Rp 11官方下载链接:https://www.axure.com/downloadthanks 2、汉化 2.1、汉化文件下载 链接: https://pan.baidu.com/s/18Clf…...

中科院1区顶刊|IF14+:多组学MR联合单细胞时空分析,锁定心血管代谢疾病的免疫治疗新靶点
中科院1区顶刊|IF14:多组学MR联合单细胞时空分析,锁定心血管代谢疾病的免疫治疗新靶点 当下,免疫与代谢性疾病的关联研究已成为生命科学领域的前沿热点。随着研究的深入,我们愈发清晰地认识到免疫系统与代谢系统之间存在着极为复…...
GB/T 43887-2024 核级柔性石墨板材检测
核级柔性石墨板材是指以可膨胀石墨为原料、未经改性和增强、用于核工业的核级柔性石墨板材。 GB/T 43887-2024核级柔性石墨板材检测检测指标: 测试项目 测试标准 外观 GB/T 43887 尺寸偏差 GB/T 43887 化学成分 GB/T 43887 密度偏差 GB/T 43887 拉伸强度…...
ffmpeg(三):处理原始数据命令
FFmpeg 可以直接处理原始音频和视频数据(Raw PCM、YUV 等),常见场景包括: 将原始 YUV 图像编码为 H.264 视频将 PCM 音频编码为 AAC 或 MP3对原始音视频数据进行封装(如封装为 MP4、TS) 处理原始 YUV 视频…...
标注工具核心架构分析——主窗口的图像显示
🏗️ 标注工具核心架构分析 📋 系统概述 主要有两个核心类,采用经典的 Scene-View 架构模式: 🎯 核心类结构 1. AnnotationScene (QGraphicsScene子类) 主要负责标注场景的管理和交互 🔧 关键函数&…...

作为点的对象CenterNet论文阅读
摘要 检测器将图像中的物体表示为轴对齐的边界框。大多数成功的目标检测方法都会枚举几乎完整的潜在目标位置列表,并对每一个位置进行分类。这种做法既浪费又低效,并且需要额外的后处理。在本文中,我们采取了不同的方法。我们将物体建模为单…...
基于Java项目的Karate API测试
Karate 实现了可以只编写Feature 文件进行测试,但是对于熟悉Java语言的开发或是测试人员,可以通过编程方式集成 Karate 丰富的自动化和数据断言功能。 本篇快速介绍在Java Maven项目中编写和运行测试的示例。 创建Maven项目 最简单的创建项目的方式就是创建一个目录,里面…...
自定义线程池1.2
自定义线程池 1.2 1. 简介 上次我们实现了 1.1 版本,将线程池中的线程数量交给使用者决定,并且将线程的创建延迟到任务提交的时候,在本文中我们将对这个版本进行如下的优化: 在新建线程时交给线程一个任务。让线程在某种情况下…...
Spring事务传播机制有哪些?
导语: Spring事务传播机制是后端面试中的必考知识点,特别容易出现在“项目细节挖掘”阶段。面试官通过它来判断你是否真正理解事务控制的本质与异常传播机制。本文将从实战与源码角度出发,全面剖析Spring事务传播机制,帮助你答得有…...

使用ch340继电器完成随机断电测试
前言 如图所示是市面上常见的OTA压测继电器,通过ch340串口模块完成对继电器的分路控制,这里我编写了一个脚本方便对4路继电器的控制,可以设置开启时间,关闭时间,复位等功能 软件界面 在设备管理器查看串口号后&…...

基于谷歌ADK的 智能产品推荐系统(2): 模块功能详解
在我的上一篇博客:基于谷歌ADK的 智能产品推荐系统(1): 功能简介-CSDN博客 中我们介绍了个性化购物 Agent 项目,该项目展示了一个强大的框架,旨在模拟和实现在线购物环境中的智能导购。它不仅仅是一个简单的聊天机器人,更是一个集…...

VSCode 没有添加Windows右键菜单
关键字:VSCode;Windows右键菜单;注册表。 文章目录 前言一、工程环境二、配置流程1.右键文件打开2.右键文件夹打开3.右键空白处打开文件夹 三、测试总结 前言 安装 VSCode 时没有注意,实际使用的时候发现 VSCode 在 Windows 菜单栏…...

vxe-table vue 表格复选框多选数据,实现快捷键 Shift 批量选择功能
vxe-table vue 表格复选框多选数据,实现快捷键 Shift 批量选择功能 查看官网:https://vxetable.cn 效果 代码 通过 checkbox-config.isShift 启用批量选中,启用后按住快捷键和鼠标批量选取 <template><div><vxe-grid v-bind"gri…...

Android Framework预装traceroute执行文件到system/bin下
文章目录 Android SDK中寻找traceroute代码内置traceroute到SDK中traceroute参数说明-I 参数(使用 ICMP Echo 请求)-T 参数(使用 TCP SYN 包) 相关文章 Android SDK中寻找traceroute代码 设备使用的是Android 11,在/s…...

生信服务器 | 做生信为什么推荐使用Linux服务器?
原文链接:生信服务器 | 做生信为什么推荐使用Linux服务器? 一、 做生信为什么推荐使用服务器? 大家好,我是小杜。在做生信分析的同学,或是将接触学习生信分析的同学,<font style"color:rgb(53, 1…...

react-pdf(pdfjs-dist)如何兼容老浏览器(chrome 49)
之前都是使用react-pdf来渲染pdf文件,这次有个需求是要兼容xp环境,xp上chrome最高支持到49,虽然说iframe或者embed都可以实现预览pdf,但为了后续的定制化需求,还是需要使用js库来渲染。 chrome 49测试环境 能用的测试…...

RKNN开发环境搭建2-RKNN Model Zoo 环境搭建
目录 1.简介2.环境搭建2.1 启动 docker 环境2.2 安装依赖工具2.3 下载 RKNN Model Zoo2.4 RKNN模型转化2.5编译C++1.简介 RKNN Model Zoo基于 RKNPU SDK 工具链开发, 提供了目前主流算法的部署例程. 例程包含导出RKNN模型, 使用 Python API, CAPI 推理 RKNN 模型的流程. 本…...
AT模式下的全局锁冲突如何解决?
一、全局锁冲突解决方案 1. 业务层重试机制(推荐方案) Service public class OrderService {GlobalTransactionalRetryable(maxAttempts 3, backoff Backoff(delay 100))public void createOrder(OrderDTO order) {// 库存扣减(自动加全…...

20250609在荣品的PRO-RK3566开发板的Android13下解决串口可以执行命令但是脚本执行命令异常的问题
20250609在荣品的PRO-RK3566开发板的Android13下解决串口可以执行命令但是脚本执行命令异常的问题 2025/6/9 20:54 缘起,为了跨网段推流,千辛万苦配置好了网络参数。 但是命令iptables -t filter -F tetherctrl_FORWARD可以在调试串口/DEBUG口正确执行。…...
[QMT量化交易小白入门]-六十二、ETF轮动中简单的评分算法如何获取历史年化收益32.7%
本专栏主要是介绍QMT的基础用法,常见函数,写策略的方法,也会分享一些量化交易的思路,大概会写100篇左右。 QMT的相关资料较少,在使用过程中不断的摸索,遇到了一些问题,记录下来和大家一起沟通,共同进步。 文章目录 相关阅读1. 策略概述2. 趋势评分模块3 代码解析4 木头…...

21-Oracle 23 ai-Automatic SQL Plan Management(SPM)
小伙伴们,有没有迁移数据库完毕后或是突然某一天在同一个实例上同样的SQL, 性能不一样了、业务反馈卡顿、业务超时等各种匪夷所思的现状。 于是SPM定位开始,OCM考试中SPM必考。 其他的AWR、ASH、SQLHC、SQLT、SQL profile等换作下一个话题…...

性能优化中,多面体模型基本原理
1)多面体编译技术是一种基于多面体模型的程序分析和优化技术,它将程序 中的语句实例、访问关系、依赖关系和调度等信息映射到多维空间中的几何对 象,通过对这些几何对象进行几何操作和线性代数计算来进行程序的分析和优 化。 其中࿰…...