选项 (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 值的选项值。

IsNone

bool

如果选项具有 None 值,则返回 true。

IsSome

bool

如果选项具有的值不是 None,则返回 true。

Some

'T option

一个静态成员,它创建一个具有不是 None 的值的选项。

'T

返回基础值,如果该值为 None,则引发 NullReferenceException

Option 模块

有一个模块叫 Option,其中包含可对选项执行各种操作的有用函数。 虽然一些函数只是重复了属性的功能,但在需要函数的上下文中,这些函数还是很有用的。 Option.isSomeOption.isNone 都是测试选项是否包含值的模块函数。 Option.get 可获取值(如果存在值)。 如果不存在任何值,则它将引发 ArgumentException

Option.bind 函数可对值执行一个函数(如果存在值)。 此函数必须只采用一个参数,并且其参数类型必须为选项类型。 此函数的返回值为另一个选项类型。

Option 模块还包含一些函数,这些函数与可用于列表、数组、序列和其他集合类型的函数相对应。 这些函数包括 Option.mapOption.iterOption.forallOption.existsOption.foldBackOption.foldOption.count。 利用这些函数,可以像使用包含零个或一个元素的集合那样使用选项。 有关更多信息和示例,请参见列表中对集合函数进行的讨论。

转换为其他类型

可以将选项转换为列表或数组。 在将选项转换为上述任一数据结构时,得到的数据结构具有零个或一个元素。 若要将选项转换为数组,请使用 Option.toArray。 若要将选项转换为列表,请使用 Option.toList

请参见

其他资源

F# 语言参考

F# 类型