選項。
當具名值或變數沒有實際值時,我們就會使用 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
。