选项
当命名值或变量可能不存在实际值时,使用 F# 中的选项类型。 选项具有基础类型,可能包含该类型的值或者可能不包含值。
注解
以下代码演示了一个生成选项类型的函数。
let keepIfPositive (a: int) = if a > 0 then Some(a) else None
如你所见,如果输入 a
大于 0,则生成 Some(a)
。 否则,会生成 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
。 根据具体情况,捕获异常而不是允许其传播可能不是合适的设计选择。
此外,仍然可以将 null
或 NULL 值传递给选项的 Some
情况。 通常是在常规 F# 编程中,这是需要避免的,但由于 .NET 中引用类型的性质,这种情况可能发生。
选项属性和方法
选项类型支持以下属性和方法。
属性或方法 | 类型 | 说明 |
---|---|---|
None |
'T option |
创建具有 None 值的选项值的静态成员。 |
IsNone | bool |
如果选项的值为 None ,则返回 true 。 |
IsSome | bool |
如果选项的值不为 None ,则返回 true 。 |
Some |
'T option |
一个静态成员,创建一个值不为 None 的选项。 |
值 | 'T |
返回基础值,如果值为 None ,则引发 System.NullReferenceException 。 |
Option 模块
有一个模块 Option,其中包含对选项执行操作的有用函数。 一些函数会重复属性的功能,但在需要函数的上下文中很有用。 Option.isSome 和 Option.isNone 都是模块函数,用于测试选项是否具有值。 Option.get 用于获取值(如果有)。 如果没有值,则会引发 System.ArgumentException
。
如果有值,Option.bind 函数会对该值执行函数。 该函数必须只接受一个参数,并且它的参数类型必须是选项类型。 函数的返回值是另一种选项类型。
选项模块还包括与可用于列表、数组、序列和其他集合类型的函数相对应的函数。 这些函数包括 Option.map
、Option.iter
、Option.forall
、Option.exists
、Option.foldBack
、Option.fold
和 Option.count
。 这些函数可用于将选项用作零个或一个元素的集合。 有关详细信息和示例,请参阅列表中有关集合函数的讨论。
转换为其他类型
选项可以转换为列表或数组。 当某个选项转换为这些数据结构中的任何一个时,生成的数据结构将包含零个或一个元素。 若要将选项转换为数组,请使用 Option.toArray
。 若要将选项转换为列表,请使用 Option.toList
。