选项 (F#)
当命名值或变量可能没有实际值时,将使用 F# 中的选项类型。 选项具有一个基础类型,它可能包含该类型的值,也可能不包含值。
备注
下面的代码阐释选项类型的用法。
let keepIfPositive (a : int) = if a > 0 then Some(a) else None
当选项没有实际值时,将使用值 None。 否则,表达式 Some( ... ) 会为选项给定一个值。 值 Some 和 None 在模式匹配中很有用,如下面的函数 exists 中所示,如果选项具有值,则该函数返回 true;否则返回 false。
let exists (x : int option) =
match x with
| Some(x) -> true
| None -> false
使用选项
通常,当搜索未返回匹配的结果时会使用选项,如下面的代码所示。
let rec tryFindMatch pred list =
match list with
| head :: tail -> if pred(head)
then Some(head)
else tryFindMatch pred tail
| [] -> None
// result1 is Some 100 and its type is int option.
let result1 = tryFindMatch (fun elem -> elem = 100) [ 200; 100; 50; 25 ]
// result2 is None and its type is int option.
let result2 = tryFindMatch (fun elem -> elem = 26) [ 200; 100; 50; 25 ]
在前面的代码中,将按递归方式搜索列表。 函数 tryFindMatch 采用一个谓词函数 pred 作为参数,该函数返回一个布尔值和要搜索的列表。 如果找到符合谓词的元素,则递归将结束,并且该函数会将相应的值作为表达式 Some(head) 中的选项返回。 当匹配空列表时,递归结束。 此时未找到值 head,并将返回 None。
很多在集合中搜索可能存在也可能不存在的值的 F# 库函数将返回 option 类型。 按照约定,这些函数应以 try 前缀开头,例如 Seq.tryFindIndex。
此外,在值可能不存在的情况下(例如,如果在尝试构造值时可能会引发异常),选项也会很有用。 下面的代码示例阐释了这一点。
open System.IO
let openFile filename =
try
let file = File.Open (filename, FileMode.Create)
Some(file)
with
| ex -> eprintf "An exception occurred with message %s" ex.Message
None
上一示例中的 openFile 函数具有类型 string -> File option,这是因为,如果成功打开文件,则该函数会返回 File 对象;如果发生异常,则返回 None。 根据不同的情况,捕获异常而不是允许异常传播这一做法可能不是合适的设计选择。
选项属性和方法
选项类型支持以下属性和方法。
属性或方法 |
类型 |
说明 |
---|---|---|
'T option |
一个静态属性,使用此属性可创建具有 None 值的选项值。 |
|
bool |
如果选项具有 None 值,则返回 true。 |
|
bool |
如果选项具有的值不是 None,则返回 true。 |
|
'T option |
一个静态成员,它创建一个具有不是 None 的值的选项。 |
|
'T |
返回基础值,如果该值为 None,则引发 NullReferenceException。 |
Option 模块
有一个模块叫 Option,其中包含可对选项执行各种操作的有用函数。 虽然一些函数只是重复了属性的功能,但在需要函数的上下文中,这些函数还是很有用的。 Option.isSome 和 Option.isNone 都是测试选项是否包含值的模块函数。 Option.get 可获取值(如果存在值)。 如果不存在任何值,则它将引发 ArgumentException。
Option.bind 函数可对值执行一个函数(如果存在值)。 此函数必须只采用一个参数,并且其参数类型必须为选项类型。 此函数的返回值为另一个选项类型。
Option 模块还包含一些函数,这些函数与可用于列表、数组、序列和其他集合类型的函数相对应。 这些函数包括 Option.map、Option.iter、Option.forall、Option.exists、Option.foldBack、Option.fold 和 Option.count。 利用这些函数,可以像使用包含零个或一个元素的集合那样使用选项。 有关更多信息和示例,请参见列表中对集合函数进行的讨论。
转换为其他类型
可以将选项转换为列表或数组。 在将选项转换为上述任一数据结构时,得到的数据结构具有零个或一个元素。 若要将选项转换为数组,请使用 Option.toArray。 若要将选项转换为列表,请使用 Option.toList。