35-match 表达式
仓颉支持两种 match
表达式,第一种是包含待匹配值的 match
表达式,第二种是不含待匹配值的 match
表达式。
含匹配值的 match 表达式
javascript
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
表达式要求所有匹配必须是穷尽(exhaustive)的,意味着待匹配表达式的所有可能取值都应该被考虑到。当 match
表达
式非穷尽,或者编译器判断不出是否穷尽时,均会编译报错
pattern guard
在 case
分支的模式之后,可以使用 pattern guard
进一步对匹配出来的结果进行判断。pattern guard
使用 where cond
表示,要求表达式 cond
的类型为 Bool
。
javascript
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)
}
没有匹配值的 match 表达式
与包含待匹配值的 match
表达式相比,关键字 match
之后并没有待匹配的表达式,并且 case
之后不再是 pattern
,而是类
型为 Bool
的表达式
javascript
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
分支中=>
之后的代码块的类型是上下文所要求的类型的子类型; - 在上下文没有明确的类型要求时,
match
表达式的类型是每个case
分支中=>
之后的代码块的类型的最小公共父类型; - 当
match
表达式的值没有被使用时,其类型为Unit
,不要求各分支的类型有最小公共父类型。
下面分别举例说明。
javascript
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
的子类型,显然上例中 =>
之后的字符串类型的字面量均满足要求。
再来看一个没有上下文类型信息的例子:
javascript
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
。