选项

当命名值或变量可能不存在实际值时,使用 F# 中的选项类型。 选项具有基础类型,可能包含该类型的值或者可能不包含值。

注解

以下代码演示了一个生成选项类型的函数。

let keepIfPositive (a: int) = if a > 0 then Some(a) else None

如你所见,如果输入 a 大于 0,则生成 Some(a)。 否则,会生成 None

当选项没有实际值时,使用值 None。 否则,表达式 Some( ... ) 为选项提供一个值。 值 SomeNone 在模式匹配中很有用,如以下函数 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.isSomeOption.isNone 都是模块函数,用于测试选项是否具有值。 Option.get 用于获取值(如果有)。 如果没有值,则会引发 System.ArgumentException

如果有值,Option.bind 函数会对该值执行函数。 该函数必须只接受一个参数,并且它的参数类型必须是选项类型。 函数的返回值是另一种选项类型。

选项模块还包括与可用于列表、数组、序列和其他集合类型的函数相对应的函数。 这些函数包括 Option.mapOption.iterOption.forallOption.existsOption.foldBackOption.foldOption.count。 这些函数可用于将选项用作零个或一个元素的集合。 有关详细信息和示例,请参阅列表中有关集合函数的讨论。

转换为其他类型

选项可以转换为列表或数组。 当某个选项转换为这些数据结构中的任何一个时,生成的数据结构将包含零个或一个元素。 若要将选项转换为数组,请使用 Option.toArray。 若要将选项转换为列表,请使用 Option.toList

另请参阅