選項
當具名值或變數的實際值可能不存在時,就會使用 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.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
。
帶預設值的選項轉換
除了轉換成清單和數位之外,您也可以使用 Option.defaultValue
函式提供預設值,將選項轉換成其他類型。 當您想確保值不是 None
時,這特別有用。 例如:
let optionString = Some("F#")
let defaultString = optionString |> Option.defaultValue ""
// defaultString is "F#"
let optionInt = None
let defaultInt = optionInt |> Option.defaultValue 0
// defaultInt is 0
Option.defaultValue
函式可讓您順暢地處理 Some
和 None
案例,而不需要模式比對。