当前位置: 首页 > news >正文

仓颉编程语言的match表达式

仓颉编程语言的match表达式

【官方文档 文档-仓颉编程语言官网 】

仓颉编程语言中支持使用模式匹配表达式(match 表达式)实现模式匹配(pattern matching),允许开发者使用更精简的代码描述复杂的分支控制逻辑。

仓颉支持两种 match 表达式,第一种是包含待匹配值的 match 表达式,第二种是不含待匹配值的 match 表达式:带值的 match 用“模式”去比对具体数据,不带值的 match 用“布尔条件”做分支。

按顺序匹配,一旦命中就立即执行对应代码,并结束整个 match;不能处理就继续往下问,直到问完为止。

match表达式可以看作是多个 if-else if-else 的简化写法。但 match 能显著提升处理多场景逻辑的效率,尤其是在枚举、复杂数据结构的场景中,优势远胜于传统的 if-else。

main() {let score = 82// if-else 写法if (score >= 90) {println("优秀")} else if (score >= 80) {println("良好")} else if (score >= 60) {println("及格")} else {println("不及格")}// match 写法(更简洁,分支更清晰)match {case score >= 90 => println("优秀")case score >= 80 => println("良好")case score >= 60 => println("及格")case _ => println("不及格")}
}

从此例看, match 确实是 if-else 的简化,减少了重复的 else if 关键字,分支逻辑更直观。但是,match 具有 if-else 无法替代能力。if-else 处理枚举(enum)、元组(tuple)、结构(struct)等复杂类型时,需要手动判断类型、提取成员,代码繁琐且易出错;而 match 的模式匹配能直接解构数据。

仓颉编程语言提供了丰富的模式种类:

常量模式

使用字面量(如整数、字节、浮点、字符、布尔、字符串、Unit),要求 字面量的类型必须和待匹配值(文档中的 selector)类型一致 且 值相等 才算匹配成功。

通配符模式

可以使用下划线 _ 通配符(wildcard),它可以匹配任意值,但不会保存匹配到的值(相当于 “忽略这个值”)。 通常放在最后兜底——作为 match 表达式的最后一个 pattern 来匹配其它 case 未覆盖到的情况,确保穷尽。

绑定模式

绑定模式( binding pattern)和通配符一样能匹配任意值,但需要将变量名写在模式里,并且会将匹配到的值绑定到一个变量,供 => 后面的代码使用。绑定模式中定义的变量是不可变的。

元组模式(tuple patterns)

元组模式用于匹配元组(Tuple)类型的值(由多个值组合成的整体,如 (a, b)、(name, age, score))。它通过 “按位置匹配元组的每个元素”,实现对元组的解构或条件判断。其中子模式的数量必须和待匹配元组的 “维度”(元素个数)完全一致。

类型模式(type patterns)

类型模式(type pattern)用于判断值的运行时类型,并自动完成类型转换(type cast)——自动向下转型,适合处理多态场景(如父类与子类的对象)。

类型模式有两种形式:

_      : 类型        // 只检查不绑定,通配符模式 _

绑定名 : 类型        // 绑定变量并转型

它们的区别是后者会发生变量绑定,而前者不会。

enum 模式

enum 模式主要和 enum (枚举)类型配合使用。

结构与枚举构造器一致:无参构造器对应 case 构造器名,带参构造器对应 case 构造器名(子模式...);

匹配条件严格:必须构造器名相同,且所有参数与子模式匹配;

穷尽性要求:match 表达式必须覆盖所有可能的构造器,否则编译器报错。

模式守卫(Pattern Guards)

即在 pattern 与 => 之间加上 where boolExpression(其中boolExpression是值为布尔类型的表达式)。匹配的过程中,只有当值与 pattern 匹配并且满足 where 之后的 boolExpression 时, case 才算匹配成功,否则匹配失败。

下面给出一组示例。

例 1:简单数字分类

main() {// ① 带匹配值let score = 85let level = match (score / 10) {case 10 | 9 => "优秀"case 8      => "良好"   // 命中,下面三行可能引发警告信息【注】case 7      => "中等"   case 6      => "及格"case _      => "不及格"}println("带匹配值: ${level}")      // 输出:带匹配值: 良好// ② 不带匹配值match {case score >= 90 => println("不带匹配值: 优秀")case score >= 80 => println("不带匹配值: 良好")  // 命中,输出:不带匹配值: 良好case score >= 70 => println("不带匹配值: 中等")case score >= 60 => println("不带匹配值: 及格")case _           => println("不带匹配值: 不及格")}
}

其中:10 | 9 不是“位运算”,而是“或模式”——只要匹配 10 或 9 就走这条分支。

【注】:当匹配值是编译时可确定的常量时,它会检查哪些分支永远不会被执行,并提示这些分支冗余:
warning: unreachable pattern
……
# note: this warning can be suppressed by setting the compiler option `-Woff unused`
(意思是
警告:不可访问的模式
……
注意:这个警告可以通过设置编译器选项“-Woff unused”来消除。)
可以不用管它。解释:
警告的本质是编译器的 “智能提醒”:当匹配值是编译时可确定的常量时,它会检查哪些分支永远不会被执行,并提示这些分支冗余。如果你的代码确实需要保留这些分支(为了扩展性),让匹配值 “动态化”(如通过函数、输入获取)即可消除警告。
如将
let score = 85
改为:
func getScore() : Int8 {
    85  // 即使返回固定值,函数调用让编译器无法提前确定
}

    print("请输入:")
    let str: String  = readln()
    let score =  Int64.parse(str)  //需要 import std.convert.*
用这两种方式之一消除警告。

例 2结合模式守卫(Pattern Guards)使用绑定的变量

main() {let score = 88//  结合条件(where)使用绑定的变量match (score) {// 匹配任意值绑定到s,再用where判断范围case s where s >= 90 => println("优秀,分数:${s}")case s where s >= 60 => println("及格,分数:${s}")  // 匹配88,输出“及格,分数:88”case s => println("不及格,分数:${s}")}
}

例 3:元组模式示例

main() {// 定义一个元组:(姓名, 分数)let scoreTuple = ("Allen", 90)// 用元组模式匹配这个元组var scoreResult: String = match (scoreTuple) { case ("Bob", 90) =>  "Bob got 90"  // 子模式都是常量:匹配("Bob", 90)case ("Allen", score) =>  "Allen got ${score}"  // 命中:第一个元素是"Allen"(常量模式),第二个元素绑定到变量score(绑定模式)case ("Allen", 100) | ("Bob", 100) =>  "Allen or Bob got 100"  // 多模式组合:匹配("Allen",100)或("Bob",100)case (_, _) =>  ""  // 通配符模式:匹配所有其他元组(兜底)}println(scoreResult)   // → Allen got 90
}

说明:

待匹配元组是 ("Allen", 90),维度为 2(2 个元素),因此所有元组模式必须包含 2 个子模式(否则不匹配)。其中子模式的数量必须和待匹配元组的 “维度”(元素个数)完全一致。

第一个 case ("Bob", 90):第一个子模式 "Bob" 与元组第一个元素 "Allen" 不匹配,跳过。

第二个 case ("Allen", score):第一个子模式 "Allen" 匹配成功,第二个子模式 score(绑定模式)将元组的 90 绑定到 score 变量,整体匹配成功,执行对应代码。

例 4类型模式(type pattern)示例

// 定义父类Point和子类ColoredPoint(多态场景)
open class Point { var x: Int32 = 1var y: Int32 = 2init(x: Int32, y: Int32) {this.x = xthis.y = y}
}
class ColoredPoint <: Point {  // 继承自Pointvar color: String = "green"init(x: Int32, y: Int32, color: String) {super(x, y)  // 调用父类构造函数this.color = color}
}main() {// 创建两个实例:父类对象和子类对象let normalPt = Point(5, 10)  // 类型是Pointlet colorPt = ColoredPoint(8, 24, "red")  // 类型是ColoredPoint(也是Point的子类)// 用类型模式匹配normalPt(Point类型)var rectangleArea1: Int32 = match (normalPt) {case _: Point => normalPt.x * normalPt.y  // 命中:normalPt是Point类型,类型匹配,计算面积case _ => 0}// 用类型模式匹配colorPt(ColoredPoint类型,是Point的子类)var rectangleArea2: Int32 = match (colorPt) {case cpt: Point => cpt.x * cpt.y  // 命中:colorPt是Point的子类,类型匹配,转换为Point类型并绑定到cptcase _ => 0}println("area1 = ${rectangleArea1}") // 50println("area2 = ${rectangleArea2}") // 192
}

说明:

对于 normalPt(类型为 Point):

case _: Point 中,_: Point 检查 normalPt 的类型是否是 Point(或其子类),显然是,因此匹配成功,执行面积计算。

对于 colorPt(类型为 ColoredPoint,是 Point 的子类):

case cpt: Point 中,cpt: Point 检查 colorPt 的类型是否兼容 Point(子类兼容父类),类型匹配;然后将 colorPt 转换为 Point 类型并绑定到 cpt,通过 cpt.x 和 cpt.y 访问属性(转换后仍可访问父类成员)。

5:枚举示例

enum TrafficLight { | Red | Yellow | Green }main() {let light = TrafficLight.Yellow// ① 带匹配值(穷尽早退)let msg = match (light) {case Red    => "停车"case Yellow => "注意"   // 命中case Green  => "通行"}println("交通灯: ${msg}")          // → 交通灯:注意// ② 不带匹配值,用变量做条件let speed = 55match {case speed > 120          => println("超速警告")case speed >= 80          => println("正常行驶")case speed > 0            => println("低速行驶")  // 命中case _                    => println("车辆静止")}
}

说明:TrafficLight 只有 3 个构造器 → 3 条 case 已全覆盖Red、Yellow、Green,不需要 _。

例 6:带多参数的枚举构造器

// 定义一个表示“形状”的枚举,包含带多参数的构造器
enum Shape {| Circle(Int)  // 圆:半径(Int)| Rectangle(Int, Int)  // 矩形:宽、高(Int, Int)| Square(Int)  // 正方形:边长(Int)
}main() {let shape = Shape.Rectangle(3, 4)  // 矩形实例:宽3,高4let area = match (shape) {case Circle(r) => 3 * r * r  // 圆面积:3×r²(简化计算)case Rectangle(w, h) => w * h  // 命中:构造器名Rectangle,参数3与w匹配,4与h匹配case Square(s) => s * s  // 正方形面积:边长²}println("面积:${area}")  // 输出:面积:12(3×4)
}

说明:

shape 是 Rectangle(3,4) 实例,case Rectangle(w, h) 中:

构造器名 Rectangle 与实例一致;

第一个参数 3 与绑定模式 w 匹配(w=3),第二个参数 4 与 h 匹配(h=4),因此匹配成功,计算面积 3×4=12。

例 7:非穷尽枚举必须用 _ 兜底,否则直接编译不过

enum HttpStatus {| Ok | NotFound | ServerError | ...
}func codeOf(s: HttpStatus): Int64 {match (s) {case Ok         => 200case NotFound   => 404case ServerError => 500case _          => -1    // 必须兜底,否则编译报错}
}main() {println(codeOf(HttpStatus.NotFound))  // → 404
}

http://www.dtcms.com/a/320722.html

相关文章:

  • 《算法导论》第 12 章 - 二叉搜索树
  • 【量子计算】量子计算驱动AI跃迁:2025年算法革命的曙光
  • conda pip uv与pixi
  • SpringCloud(4)-多机部署,负载均衡-LoadBalance
  • ASP.NET三层架构成绩管理系统源码
  • HBase的异步WAL性能优化:RingBuffer的奥秘
  • 深度虚值期权合约有什么特点?
  • InfoNCE 损失
  • 企微消息机器人推送配置-windows+python
  • 【ros-humble】2.自定义通讯接口发布者python,qt使用(话题)
  • 关于csdn导入和导出
  • USB2.0协议学习-基础知识
  • day070-Jenkins自动化与部署java、前端代码
  • linux安装mysql8.0,二进制码安装
  • 《Graph machine learning for integrated multi-omics analysis》
  • ChipCamp探索系列 -- 1. Soft-Core RISC-V on FPGA
  • 【全栈自动驾驶与异构加速】系统学习计划
  • React 状态管理入门:从 useState 到复杂状态逻辑
  • 【MongoDB】查询条件运算符:$expr 和 $regex 详解,以及为什么$where和$expr难以使用索引
  • 使用pybind11封装C++API
  • HTML <picture> 元素:让图片根据设备 “智能切换” 的响应式方案
  • 数据结构(16)排序(上)
  • 时序数据库-涛思数据库
  • 6.Linux 系统上的库文件生成与使用
  • Linux 内核发包流程与路由控制实战
  • 医防融合中心-智慧化慢病全程管理医疗AI系统开发(上)
  • 後端開發技術教學(三) 表單提交、數據處理
  • 排序知识总结
  • 五、mysql8.0在linux中的安装
  • 引领云原生时代,华为云助您构建敏捷未来