一键导入
cangjie-pattern-match
仓颉语言模式匹配。当需要了解 match 表达式、模式类型(常量/通配符/绑定/元组/类型/枚举)、模式嵌套、模式守卫(where)、穷举性、模式可反驳性、if-let 条件匹配、while-let 循环匹配、模式在变量定义和 for-in 中的使用等特性时,应使用此 Skill
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
仓颉语言模式匹配。当需要了解 match 表达式、模式类型(常量/通配符/绑定/元组/类型/枚举)、模式嵌套、模式守卫(where)、穷举性、模式可反驳性、if-let 条件匹配、while-let 循环匹配、模式在变量定义和 for-in 中的使用等特性时,应使用此 Skill
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
通用算法与数据结构实现参考——排序、搜索、动态规划、图算法、字符串处理的多语言惯用写法和模板代码(Python/C++/Java/Go/Cangjie)
仓颉语言算法与数据结构实现参考——排序、搜索、动态规划、图算法、字符串处理、集合操作的惯用写法和模板代码
仓颉编程语言基本概念和规则,当需要了解关键字、标识符、程序结构、变量定义(let/var/const)、值类型与引用类型、作用域规则、表达式(if/while/for-in/break/continue)、函数等基本概念时,应使用此 Skill
仓颉语言基本数据类型。当需要了解仓颉语言的整数、浮点、布尔、字符(Rune)、字符串(String)、Unit、Nothing、元组(Tuple)、数组(Array/VArray)、区间(Range)类型以及基本运算符的语法和规则时,应使用此 Skill。
仓颉程序与C程序互操作指导,包括foreign声明、CFunc、inout参数、unsafe块、调用约定、类型映射(基础类型/结构体/CPointer/VArray/CString)、C回调仓颉、内存管理等特性时,应使用此 Skill
仓颉语言类。当需要了解仓颉语言的类定义、抽象类、构造函数(init/主构造函数)、终结器(~init)、继承(单继承/sealed)、重写(override)、重定义(redef)、成员变量、成员函数、属性(prop)、访问修饰符、This类型、对象创建等特性时,应使用此 Skill。
| name | cangjie-pattern-match |
| description | 仓颉语言模式匹配。当需要了解 match 表达式、模式类型(常量/通配符/绑定/元组/类型/枚举)、模式嵌套、模式守卫(where)、穷举性、模式可反驳性、if-let 条件匹配、while-let 循环匹配、模式在变量定义和 for-in 中的使用等特性时,应使用此 Skill |
match (expr) {
case pattern1 => exprs // 不需要用 {} 包裹
case pattern2 => exprs // 不需要用 {} 包裹
case _ => exprs // 不需要用 {} 包裹
}
规则:
=> 后是 exprs(1~N 个表达式),多个时各占一行,不需要用 {} 包裹case 前结束| 连接多个同类模式_ 兜底... 构造器)须用 _ 或绑定模式覆盖(详见 cangjie-enum Skill)main() {
let opt: ?Int64 = 42 // Option<Int64>,枚举类型
let result = match (opt) {
case Some(x) => // 枚举模式
let doubled = x * 2
println("doubled = ${doubled}")
doubled // 所执行分支最后一个表达式的值,就是 match 表达式的值
case None => 0
}
println(result) // 84
}
// ❌ 错误:case 分支不使用 {} 包裹
// match (x) {
// case 1 => { println("one"); 1 }
// }
// ✅ 正确:直接写多行表达式
match (x) {
case 1 =>
println("one")
1
case _ => 0
}
每个 case 接受 Bool 表达式(非模式),_ 表示 true,不支持模式守卫:
let x = -1
match {
case x > 0 => print("positive")
case x < 0 => print("negative") // 匹配
case _ => print("zero")
}
where)模式后添加 where condition(Bool 类型),case 仅在模式匹配且守卫为 true 时匹配。注意:仓颉使用 where,而非 if:
enum RGBColor {
| Red(Int16) | Green(Int16) | Blue(Int16)
}
main() {
let c = RGBColor.Green(-100)
let cs = match (c) {
case Green(g) where g < 0 => "Green = 0" // 匹配
case Green(g) => "Green = ${g}"
case Red(r) where r < 0 => "Red = 0"
case Red(r) => "Red = ${r}"
case Blue(b) where b < 0 => "Blue = 0"
case Blue(b) => "Blue = ${b}"
}
println(cs) // Green = 0
}
Unit,无公共父类型要求Unit 字面量| 组合Rune 值可用 Rune 字面量或单字符字符串字面量匹配Byte 值可用 ASCII 字符串字面量匹配let score = 80
let level = match (score) {
case 0 | 10 | 20 | 30 | 40 | 50 => "D"
case 60 => "C"
case 70 | 80 => "B"
case 90 | 100 => "A"
case _ => "invalid"
}
println(level) // B
_)匹配任意值,通常用作最后一个 case 兜底。
id)id,作用域到该 case 结束| 连接使用;若 id 是枚举构造器名则视为枚举模式match (x) {
case 0 => "zero"
case n => "x = ${n}" // n 绑定 x 的值
}
(p_1, p_2, ..., p_n)(n ≥ 2),每个位置匹配时整体匹配。同一模式内不允许重复绑定名。
match (("Alice", 24)) {
case ("Bob", age) => "Bob is ${age}"
case ("Alice", age) => "Alice is ${age}" // 匹配
case (_, _) => "someone"
}
_: Type(无绑定)或 id: Type(有绑定),检查运行时类型是否为 Type 的子类型,匹配时转换并可选绑定。
open class Base {
var a: Int64
public init() { a = 10 }
}
class Derived <: Base {
public init() { a = 20 }
}
match (Derived()) {
case b: Base => b.a // 匹配:Derived 是 Base 子类型,r = 20
case _ => 0
}
C(无参)或 C(p_1, ..., p_n)(有参),类型前缀可省略_;含绑定变量时不能用 |enum TimeUnit {
| Year(UInt64) | Month(UInt64)
}
match (Year(2)) {
case Year(n) => "${n * 12} months" // 匹配
case Month(n) => "${n} months"
}
元组和枚举模式可任意深度嵌套:
enum TimeUnit { | Year(UInt64) | Month(UInt64) }
enum Command { | SetTimeUnit(TimeUnit) | Quit }
match ((SetTimeUnit(Year(2024)), true)) {
case (SetTimeUnit(Year(y)), true) => println("year ${y}") // 匹配
case _ => ()
}
| 模式 | 可反驳性 | 规则 |
|---|---|---|
| 常量 | 始终可反驳 | 可能不匹配 |
通配符 _ | 始终不可反驳 | 总匹配 |
绑定 id | 始终不可反驳 | 总匹配 |
类型 id: Type | 始终可反驳 | 运行时类型可能不匹配 |
元组 (p1,...,pn) | 所有 pi 不可反驳时不可反驳 | 一个可反驳 → 整体可反驳 |
枚举 C(p1,...,pn) | 仅一个有参构造器且所有 pi 不可反驳时不可反驳 | 多构造器 → 始终可反驳 |
let (x, y) = (100, 200) // 元组解构
for ((i, j) in [(1, 2), (3, 4)]) { println(i + j) } // for-in 元组解构
适用于不可反驳模式
在 if 条件中使用 let pattern <- expression 语法糖,匹配成功进入 if 分支,绑定变量仅在 if 分支内可用。<- 右侧表达式优先级不能低于 ..,必要时用 () 包裹。
enum Msg {
| Text(String) | Quit
}
main() {
let m: Msg = Text("hello")
if (let Text(s) <- m) {
println(s) // hello
} else {
println("not text")
}
}
&&)&& 可连接多个 let 模式或与布尔表达式混合,前面绑定的变量可在后续条件中使用:
enum Expr {
| Num(Int64) | Error
}
main() {
let a = Num(42)
let b = Num(10)
// 两个 let 模式同时匹配
if (let Num(x) <- a && let Num(y) <- b) {
println("sum = ${x + y}") // sum = 52
}
// let 模式 + 布尔条件
if (let Num(n) <- a && n > 0) {
println("positive: ${n}") // positive: 42
}
}
||)|| 连接时,模式中不能有变量绑定,只能使用通配符 _:
let a = Num(1)
let b: Expr = Error
if (let Num(_) <- a || let Num(_) <- b) {
println("至少一个是 Num") // 匹配
}
|| 连接的模式不能绑定变量&& 右侧须为 let pattern 或 Bool 表达式let 左侧使用else 分支使用&& 做额外检查,不用 where(where 仅用于 match 模式守卫)// ❌ 错误示例
// if (let Num(a) <- x || a > 1) {} // || 连接的模式不能绑定变量
// if (a > 3 && let Num(a) <- x) {} // a 在绑定前使用
// if (let Num(a) <- x where a > 3) {} // 应使用 && 而非 where
// if (let Num(a) <- x && a > 0) {
// println(a)
// } else {
// println(a) // ❌ a 不能在 else 分支使用
// }
在 while 条件中使用 let pattern <- expression,匹配成功时执行循环体,失败时退出循环。条件规则与 if-let 相同。
enum State {
| Active(Int64) | Done
}
main() {
var s: State = Active(1)
while (let Active(n) <- s) {
println(n)
s = if (n < 3) { Active(n + 1) } else { Done }
}
// 输出:1 2 3
}
等价的 match 解糖形态:
while (true) {
match (s) {
case Active(n) =>
println(n)
s = if (n < 3) { Active(n + 1) } else { Done }
case _ => break
}
}
enum Shape {
| Circle(Float64)
| Rect(Float64, Float64)
| Triangle(Float64, Float64)
}
main() {
let shapes = [Circle(5.0), Rect(3.0, 4.0), Triangle(3.0, 6.0)]
for (shape in shapes) {
let area = match (shape) {
case Circle(r) => 3.14159 * r * r
case Rect(w, h) => w * h
case Triangle(b, h) => b * h / 2.0
}
match {
case area > 50.0 => println("Large: ${area}")
case area > 10.0 => println("Medium: ${area}")
case _ => println("Small: ${area}")
}
}
}