Rust特殊枚举Option用法


Rust特殊枚举Option用法文章插图
在上一节中 , 我们研究了IpAddr枚举如何使我们使用Rust的类型系统对更多信息进行编码 , 而不仅仅是将数据编码到程序中 。 本节探讨的案例研究Option , 这是标准库定义的另一个枚举 。 Option类型在很多地方都使用 , 因为它对非常常见的情况进行编码 , 在这种情况下 , 值可以是某些值 , 也可以是任何值 。 用类型系统来表达这个概念意味着编译器可以检查您是否已经处理了所有您应该处理的情况 。 此功能可以防止其他编程语言中极为常见的错误 。
【Rust特殊枚举Option用法】通常会根据所包含的功能来考虑编程语言设计 , 但是所排除的功能也很重要 。 Rust没有许多其他语言具有的null功能 。 Null是一个值 , 表示那里没有任何值 。 在具有null的语言中 , 变量始终可以处于以下两种状态之一:null或非null 。
null的发明者Tony Hoare在2009年的演讲“ Null References:十亿美元的错误”中说:
我称之为我的十亿美元错误 。 当时 , 我正在设计第一个全面的类型系统 , 以面向对象的语言进行引用 。 我的目标是确保所有对引用的使用都绝对安全 , 并由编译器自动执行检查 。 但是我无法抗拒引入空引用的诱惑 , 仅仅是因为它是如此容易实现 。 这导致了无数错误 , 漏洞和系统崩溃 , 在最近四十年中可能造成十亿美元的痛苦和破坏 。
空值的问题在于 , 如果您尝试将空值用作非空值 , 则会出现某种错误 。 由于此null或not-null属性无处不在 , 因此很容易产生这种错误 。
但是 , null试图表达的概念仍然是一个有用的概念:null是当前由于某种原因而无效或不存在的值 。
问题不在于概念 , 而在于特定的实现 。 这样 , Rust没有空值 , 但是它确实有一个枚举 , 该枚举可以编码存在或不存在的值的概念 。 该枚举是 Option , 由标准库 定义如下:
enum Option {Some(T),None,}Option枚举是非常有用 , 它甚至包括中拉开序幕; 您无需将其明确纳入范围 。 此外 , 这样是它的变体:你可以使用Some和None直接不带Option::前缀 。 该 Option枚举仍然只是一个普通的枚举 , 并Some(T)和None类型仍然变种Option 。
语法是 , 我们还没有谈到尚Rust的特点 。 这是一个泛型类型参数 , 我们将在第10章中更详细地介绍泛型 。 现在 , 您只需要知道 , 这意味着枚举的Some变体 Option可以容纳任何类型的数据 。 以下是一些使用Option值保存数字类型和字符串类型的示例:
let some_number = Some(5);let some_string = Some("a string");let absent_number: Option = None;如果使用None而不是Some , 则需要告诉RustOption我们拥有哪种类型, 因为编译器无法Some 通过仅查看一个None值来推断该变量将拥有的类型 。
当我们拥有一个Some值时 , 我们知道存在一个值并将该值保存在内Some 。 None从某种意义上说 , 当我们拥有一个值时 , 它与null含义相同:我们没有一个有效的值 。 那么 , 为什么有 Option比没有更好呢?
简而言之 , 因为Option和T(T可以是任何类型)是不同的类型 , 所以编译器不会让我们使用Option值 , 就好像它绝对是有效值一样 。 例如 , 此代码不会编译 , 因为它正在尝试向中添加i8一个Option
let x: i8 = 5;let y: Option = Some(5);let sum = x + y;如果运行此代码 , 则会收到如下错误消息:
$ cargo runCompiling enums v0.1.0 (file:///projects/enums)error[E0277]: cannot add `std::option::Option` to `i8` --> src/main.rs:5:17|5 |let sum = x + y;|^ no implementation for `i8 + std::option::Option