CppCon 2015 学习:Simple, Extensible Pattern Matching in C++14

发布于:2025-06-11 ⋅ 阅读:(17) ⋅ 点赞:(0)

什么是 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