Rust 从 0 到 1- 枚举 -match 控制流
match 是 Rust 的一个极为强大的控制流运算符,类似 switch,但 match 更强大,它允许我们将一个值与一系列的“模式”相比较,并根据相匹配的“模式”执行相应代码。“模式”可由文本、变量、通配符等等构成(后面会介绍不同种类的模式以及它们的作用),非常灵活并且编译器还会确保所有可能的情况都做了处理。
可以把 match 想象成某种硬币分类器:硬币会滑入第一个符合它大小的孔洞。同样地,match 也会将值同每一个模式逐个匹配,并且在遇到第一个 “符合” 的模式时,进入相关联的代码块执行。下面我们就用“硬币”作为一个使用 match 的例子!编写一个函数确定“硬币”的种类并返回它的面值:
match 关键字后的表达式(在这个例子中是 coin )看起来和 if 使用的表达式很像,不过它们有一个非常大的区别:对于 if,表达式必须返回一个布尔值,而对于 match, 表达式可以是任何类型的。在执行时,表达式的值将按顺序与每一个分支的“模式”匹配。如果符合,则这个模式相关联的代码将被执行;如果不匹配,就继续执行下一个分支。每个分支执行的结果值将作为整个 match 表达式的返回值。
获取枚举成员关联的值
1999 年到 2008 年间,25 美分的硬币的一侧设计有美国 50 个州的不同图案。假设我们尝试收集所有 50 个州图案的 25 美分硬币,也就说,在根据硬币类型分类的同时,我们也想知道每个 25 美分硬币所对应的州,这样如果我们还没有这个州的话,可以将其加入收藏。那么应该怎么做呢?我们可以将这些信息加入枚举成员里,修改 Quarter 成员来包含一个 State 值;然后,我们在 Coin::Quarter 分支中增加了一个 state 变量,当匹配到 Coin::Quarter 时,变量 state 将会绑定 coin 所对应的州,接着就可以在分支代码中使用 state 进行处理(在例子里我们只是简单的打印出来):
匹配 Option<T>
我们在之前的部分介绍过 Option<T> 的定义,但是没介绍如何使用。比如我们想要编写一个函数,它的参数是 Option<i32> 并且如果其中有值,将其加一;如果其中没有值,返回 None 值并不执行任何操作。我们可以通过 match 非常简单的实现:
将 match 与枚举结合使用的场景非常常见。你会在 Rust 代码中看到很多这样的例子:match 一个枚举,绑定其中的值到一个或多个变量,接着在执行代码中使用这些值。根据官方文档的说法,这一直是用户的最爱。
匹配分支是穷尽的
match 还有一个地方需要讨论。参考下面 plus_one 函数的实现,无法编译通过:
这是由于代码没有处理 None 的情况,这样的代码可能会产生 bug。Rust 不允许这种情况发生,Rust 知道我们没有覆盖所有可能的情况甚至知道哪些“模式”被忘记了!Rust 要求必须穷举所有可能的“模式”。在这个 Option<T> 的例子中,编译器会提醒我们没有处理 None 的情况,这使我们免于造成之前提到过的价值亿万的错误。
_ 通配符
如果表达式是一个 u32 ,要穷举所有可能的“模式”,我想我们可能要疯了,别着急,Rust 提供了一种方法用于处理这种场景。例如,u8 拥有 0 到 255 的 256 个值,如果我们只关心 1、3、5 和 7 这几个值,那其余的值可以使用通配符 _ 替代(类似 swith 里的 default):
_ 可以匹配任何值。通过将其放置于其他分支之后,_ 将会匹配所有之前没有指定的值。在例子中 _ 返回 () ,即 unit 类型(在前面讲结构体的时候提到过),也就是说对其余的值不做任何处理,也不返回任何有意义的值。
版权声明: 本文为 InfoQ 作者【山】的原创文章。
原文链接:【http://xie.infoq.cn/article/18422404d3f29b3f2e804373a】。文章转载请联系作者。
评论