在 Gleam 中,可以使用case表达式有条件地执行代码。借助 case 表达式,可以拿一个值去匹配一个或多个_模式_。其中一种模式是_字面量模式_,它把值和字面量(例如 1 或 "hello")进行匹配。
case 表达式使用 case关键字编写:
pub fn describe(number: Int) -> String {
case number {
0 -> "Zero"
1 -> "One"
}
}
虽然这看起来像其他语言中的switch语句,但只有在同时使用其他模式时,模式匹配才真正展现出优势。其中一种模式是_变量模式_,它允许把值赋给变量。在这个例子中,如果 number 不为 0,变量 i 就会被赋予 number 的值:
pub fn describe(number: Int) -> String {
case number {
0 -> "Zero"
i -> "Non zero"
}
}
有时你可能想给模式添加一个额外的条件。这被称为_守卫_(子句),可以用 if关键字添加:
pub fn describe(number: Int) -> String {
case number {
0 -> "Zero"
i if i < 0 -> "Negative number"
}
}
出于性能考虑,守卫中只允许使用基本的数学运算符和布尔运算符,不能使用其他函数。
在上面的例子中,并非所有可能的输入都有匹配的模式。编译器会检测到这一点并输出错误。这被称为_穷尽性检查_。要消除这个警告,必须处理所有情况。为此,可以使用_丢弃模式_,它能匹配任何值:
pub fn describe(number: Int) -> String {
case number {
0 -> "Zero"
i if i < 0 -> "Negative number"
_ -> "Positive number"
}
}
// No compiler error
在一个子句中可以用 |分隔来匹配多个模式。每个子句只能添加一个守卫:
pub fn describe(number: Int) -> String {
let yell = True
case number {
0 -> "Zero"
3 | 5 -> "One of the first odd prime numbers"
2 | 4 | 6 | 8 if !yell -> "One of the even numbers less than 10"
i if i % 2 == 0 && yell -> "[Yelling] I'm telling you! It's a even nunber"
i if i < 0 -> "Negative number"
_ -> "Positive number"
}
}
// No compiler error
case 表达式会从上到下依次拿值与每个模式进行匹配,直到找到匹配的模式,并执行与该模式关联的逻辑。模式的顺序很重要!
在这个练习中,你要和朋友玩一个猜数字游戏。规则很简单:你秘密选一个1到100之间的数字,然后由朋友来猜你选的是哪个数。为了帮助朋友,你要根据猜测与你所选数字(42)的接近程度给出不同的回应。不同回应遵循以下规则:
42:“Correct”41或43:“So close”41:“Too low”43:“Too high”你需要完成四个任务,分别实现对不同猜测的回应。
实现reply函数,让它能回应猜中的情况:
reply(42)
// -> "Correct"
修改reply函数,让它能回应接近的猜测:
reply(41)
// -> "So close"
修改reply函数,让它能回应过低的猜测:
reply(25)
// -> "Too low"
修改reply函数,让它能回应过高的猜测:
reply(88)
// -> "Too high"