仓颉编程语言:match 表达式

match 表达式的定义

仓颉支持两种 match 表达式,第一种是包含待匹配值的 match 表达式,第二种是不含待匹配值的 match 表达式。

含匹配值的 match 表达式

main() {
    let x = 0
    match (x) {
        case 1 => let r1 = "x = 1"
                  print(r1)
        case 0 => let r2 = "x = 0" // Matched.
                  print(r2)
        case _ => let r3 = "x != 1 and x != 0"
                  print(r3)
    }
}

match 表达式以关键字 match 开头,后跟要匹配的值(如上例中的 x,x 可以是任意表达式),接着是定义在一对花括号内的若干 case 分支。

每个 case 分支以关键字 case 开头,case 之后是一个模式或多个由 | 连接的相同种类的模式(如上例中的 1、0、_ 都是模式,详见模式概述章节);模式之后可以接一个可选的 pattern guard,表示本条 case 匹配成功后额外需要满足的条件;接着是一个 =>,=> 之后即本条 case 分支匹配成功后需要执行的操作,可以是一系列表达式、变量和函数定义(新定义的变量或函数的作用域从其定义处开始到下一个 case 之前结束),如上例中的变量定义和 print 函数调用。

match 表达式执行时依次将 match 之后的表达式与每个 case 中的模式进行匹配,一旦匹配成功(如果有 pattern guard,也需要 where 之后的表达式的值为 true;如果 case 中有多个由 | 连接的模式,只要待匹配值和其中一个模式匹配则认为匹配成功)则执行 => 之后的代码然后退出 match 表达式的执行(意味着不会再去匹配它之后的 case),如果匹配不成功则继续与它之后的 case 中的模式进行匹配,直到匹配成功(match 表达式可以保证一定存在匹配的 case 分支)。

上例中,因为 x 的值等于 0,所以会和第二条 case 分支匹配(此处使用的是常量模式,匹配的是值是否相等,详见常量模式章节),最后输出 x = 0。

编译并执行上述代码,输出结果为:

x = 0

match 表达式要求所有匹配必须是穷尽(exhaustive)的,意味着待匹配表达式的所有可能取值都应该被考虑到。当 match 表达式非穷尽,或者编译器判断不出是否穷尽时,均会编译报错,换言之,所有 case 分支(包含 pattern guard)所覆盖的取值范围的并集,应该包含待匹配表达式的所有可能取值。常用的确保 match 表达式穷尽的方式是在最后一个 case 分支中使用通配符模式 _,因为 _ 可以匹配任何值。

match 表达式的穷尽性保证了一定存在和待匹配值相匹配的 case 分支。下面的例子将编译报错,因为所有的 case 并没有覆盖 x 的所有可能取值:

func nonExhaustive(x: Int64) {
    match (x) {
        case 0 => print("x = 0")
        case 1 => print("x = 1")
        case 2 => print("x = 2")
    }
}

在 case 分支的模式之后,可以使用 pattern guard 进一步对匹配出来的结果进行判断。pattern guard 使用 where cond 表示,要求表达式 cond 的类型为 Bool。

在下面的例子中(使用到了 enum 模式,详见 enum 模式章节),当 RGBColor 的构造器的参数值大于等于 0 时,输出它们的值,当参数值小于 0 时,认为它们的值等于 0:

enum RGBColor {
    | Red(Int16) | Green(Int16) | Blue(Int16)
}
main() {
    let c = RGBColor.Green(-100)
    let cs = match (c) {
        case Red(r) where r < 0 => "Red = 0"
        case Red(r) => "Red = ${r}"
        case Green(g) where g < 0 => "Green = 0" // Matched.
        case Green(g) => "Green = ${g}"
        case Blue(b) where b < 0 => "Blue = 0"
        case Blue(b) => "Blue = ${b}"
    }
    print(cs)
}

编译执行上述代码,输出结果为:

Green = 0

没有匹配值的 match 表达式

main() {
    let x = -1
    match {
        case x > 0 => print("x > 0")
        case x < 0 => print("x < 0") // Matched.
        case _ => print("x = 0")
    }
}

与包含待匹配值的 match 表达式相比,关键字 match 之后并没有待匹配的表达式,并且 case 之后不再是 pattern,而是类型为 Bool 的表达式(上述代码中的 x > 0 和 x < 0)或者 _(表示 true),当然,case 中也不再有 pattern guard。

无匹配值的 match 表达式执行时依次判断 case 之后的表达式的值,直到遇到值为 true 的 case 分支;一旦某个 case 之后的表达式值等于 true,则执行此 case 中 => 之后的代码,然后退出 match 表达式的执行(意味着不会再去判断该 case 之后的其他 case)。

上例中,因为 x 的值等于 -1,所以第二条 case 分支中的表达式(即 x < 0)的值等于 true,执行 print("x < 0")。

编译并执行上述代码,输出结果为:

x < 0

match 表达式的类型

对于 match 表达式(无论是否有匹配值),

  • 在上下文有明确的类型要求时,要求每个 case 分支中 => 之后的代码块的类型是上下文所要求的类型的子类型;

  • 在上下文没有明确的类型要求时,match 表达式的类型是每个 case 分支中 => 之后的代码块的类型的最小公共父类型;

  • 当 match 表达式的值没有被使用时,其类型为 Unit,不要求各分支的类型有最小公共父类型。

下面分别举例说明。

let x = 2
let s: String = match (x) {
    case 0 => "x = 0"
    case 1 => "x = 1"
    case _ => "x != 0 and x != 1" // Matched.
}

上面的例子中,定义变量 s 时,显式地标注了其类型为 String,属于上下文类型信息明确的情况,因此要求每个 case 的 => 之后的代码块的类型均是 String 的子类型,显然上例中 => 之后的字符串类型的字面量均满足要求。

再来看一个没有上下文类型信息的例子:

let x = 2
let s = match (x) {
    case 0 => "x = 0"
    case 1 => "x = 1"
    case _ => "x != 0 and x != 1" // Matched.
}

上例中,定义变量 s 时,未显式标注其类型,因为每个 case 的 => 之后的代码块的类型均是 String,所以 match 表达式的类型是 String,进而可确定 s 的类型也是 String。

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing ,不定期分享原创知识。

<think> 首先,用户的问题是关于仓颉编程语言中的match表达式。他们提供了一个代码示例,并问case分支属于什么模式。 用户提供的代码是: ```javascript enum RGBColor{ Red(Int16) Green(Int16) Blue(Int16) } func foo(c: RGBColor) { let cs = match(c){ case Red(r)=>"Red = $(r)" case Green(g)=>"Green $(g)" case Blue(b)=>"Blue = $(b)" } print(cs) } ``` 用户问:这个match表达式的case分支属于什么模式。 根据系统级指令,我需要参考站内引用。引用中提到了几个相关的点: - 引用[1]展示了带有where条件的枚举模式匹配。 - 引用[2]描述了模式匹配在仓颉语言中是通过match表达式实现的。 - 引用[3]解释了类型模式匹配,其中对于枚举类型,模式匹配会检查运行时类型。 - 引用[4]提到仓颉支持枚举中的同名构造器,但参数不同。 在用户代码中,枚举RGBColor有三个构造器:Red、Green、Blue,每个都带有一个Int16参数。在match表达式中,case分支是: - case Red(r) => ... - case Green(g) => ... - case Blue(b) => ... 这些case分支匹配枚举的构造器,并提取参数。 根据引用[3],对于枚举模式,模式匹配会匹配构造器并将参数绑定到变量。 具体来说,在引用[3]中,它说:"对于待匹配值 v 和类型模式 id: Type(或 _: Type),首先判断 v 的运行时类型是否是 Type 的子类型...",但这是在讨论类类型模式。 对于枚举,引用[1]和[4]更相关。引用[1]中使用了类似的结构:case Red(r) where ...,表明Red(r)是一个模式。 在仓颉语言中,这种模式称为"枚举构造器模式"或类似的。从引用看,它类似于代数数据类型的解构。 模式匹配中的这种分支称为"构造器模式"(constructor pattern),因为它匹配枚举的构造器并提取参数。 在引用[2]中,它说:"模式匹配是一种强大的工具,用于检查数据结构、提取值",并提到match表达式。 在引用[3],它讨论了类型模式,但这里是枚举,不是类。 在仓颉中,枚举有自己的模式匹配规则。 从用户代码看,case Red(r) 的模式是匹配RGBColor的Red变体,并将参数绑定到r。 因此,这种模式应该称为"枚举构造器模式"或简称为"构造器模式"。 在引用[1]中,它使用了"case Red(r) where ...",并称之为模式匹配。 类似地,在Haskell或Rust中,这被称为"数据构造器模式"。 所以,对于仓颉语言,我可以说case分支属于"枚举构造器模式"或"构造器绑定模式"。 现在,回答用户的问题。 我需要用中文回答,结构清晰。 步骤: 1. 回顾用户的问题。 2. 分析代码。 3. 解释模式类型。 4. 引用站内引用支持。 最后,添加相关问题,因为系统指令说"生成相关问题"。 系统指令:"5.生成相关问题" 在回答末尾添加相关问题。 引用格式:在段落末尾自然地添加引用标识,例如[^1]。我需要参考提供的引用。 提供的引用是: - [^1]:来自引用[1],展示了带where的枚举匹配。 - [^2]:来自引用[2],介绍模式匹配。 - [^3]:来自引用[3],解释类型模式。 - [^4]:来自引用[4],讨论枚举构造器。 在回答中,我可以引用这些。 例如,说到模式匹配时,引用[^2]。 说到枚举构造器时,引用[^4]。 在用户代码中,没有where条件,所以是简单的构造器模式。 回答结构: - 先确认问题。 - 解释代码中的match表达式。 - 指出case分支的模式类型。 - 给出解释。 - 添加相关问题。 相关问题示例: 1. 如何在仓颉中使用where条件进行模式匹配? 2. 枚举模式匹配的性能如何? 3. 仓颉模式匹配支持哪些其他模式类型? 确保使用正确的LaTeX格式:行内数学用$...$,独立公式用$$...$$,但这里可能不需要数学表达式。 在回答中,没有数学,所以只需注意代码块。 代码块用```...```格式。 最后,输出在用户可见层。 </think>### 仓颉编程语言match 表达式的 case 分支模式分析 在您提供的仓颉编程语言代码中,match 表达式的 case 分支(如 `case Red(r) => "Red = $(r)"`)属于**枚举构造器模式**(Constructor Pattern for Enums)。这种模式是仓颉语言中模式匹配的核心机制之一,用于解构枚举值并提取其关联的参数。下面我将逐步解释: #### 代码分析 您的代码定义了一个枚举类型 `RGBColor`,包含三个构造器:`Red`、`Green` 和 `Blue`,每个构造器都带有一个 `Int16` 类型的参数。在 `foo` 函数中,`match(c)` 表达式对输入值 `c`(类型为 `RGBColor`)进行模式匹配: - `case Red(r) => ...`:匹配 `RGBColor.Red` 构造器,并将构造器的参数值绑定到变量 `r`。 - `case Green(g) => ...`:匹配 `RGBColor.Green` 构造器,并将参数绑定到 `g`。 - `case Blue(b) => ...`:匹配 `RGBColor.Blue` 构造器,并将参数绑定到 `b`。 #### 模式类型详解:枚举构造器模式 在仓颉语言中,枚举构造器模式专门用于处理枚举类型。其工作原理如下: - **匹配机制**:当 `match` 表达式执行时,它会检查输入值 `c` 的运行时类型是否与某个 case 分支的构造器匹配。例如,如果 `c` 是 `RGBColor.Red(10)`,则 `case Red(r)` 分支会被触发。 - **参数提取**:模式中的变量(如 `r`、`g`、`b`)用于绑定构造器的参数值。在您的代码中,`r` 会接收 `Red` 构造器的 `Int16` 参数,并在结果字符串中使用(如 `"Red = $(r)"`)。 - **模式特性**:这种模式是“解构式”的,它不进行类型转换或子类型检查(区别于类型模式),而是直接基于枚举构造器的名称和参数结构进行匹配。如果枚举定义中构造器包含多个参数(如 `RGBColor.Red(Int16, String)`),模式需对应所有参数(如 `case Red(r, s) => ...`),但您的代码中每个构造器只有一个参数,因此模式是单变量绑定[^1][^4]。 这种模式的优势在于简洁性和安全性:它确保了所有枚举变体都被显式处理(如果缺少分支,编译器会报错),并避免了运行时的空值错误[^2]。 #### 与其他模式的对比 - **区别于类型模式**:类型模式(如 `case b: Base => ...`)用于类层次结构,检查运行时类型是否子类型,并进行类型转换(如引用[3]中的示例)。但您的代码涉及的是枚举,而非类,因此使用的是纯枚举构造器模式[^3]。 - **区别于带条件模式**:引用[1]中展示了带 `where` 条件的枚举构造器模式(如 `case Green(g) where g < 0 => ...`),但您的代码是基础形式,没有附加条件[^1]。 - **通用性**:仓颉的模式匹配支持多种模式(如通配符模式 `_` 或常量模式),但在此代码中仅使用了枚举构造器模式[^2]。 #### 总结 在您的代码中,`match` 表达式的 case 分支明确属于**枚举构造器模式**。这种模式是仓颉处理枚举值的标准方式,它高效且易于维护。如果您在代码中添加 `where` 条件(如引用[1]),它会演变为带条件的枚举构造器模式,但核心机制不变[^1][^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值