オプション

指定した値または変数に実際の値が存在しない可能性がある場合は、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 関数では、ファイルが正常に開かれた場合は File オブジェクトが返され、例外が発生した場合は None が返されるため、string -> File option 型が使用されています。 状況によっては、例外の伝達を許可するのではなくキャッチするのが、設計の適切な選択ではない場合があります。

また、オプションの Some のケースに、null または null である値を渡すこともできます。 通常、これは回避すべきであり、一般的な 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 関数は、値がある場合、値に対して関数を実行します。 関数は、引数を 1 つだけ受け取る必要があり、パラメーターの型はオプション型である必要があります。 関数の戻り値は、別のオプション型です。

Option モジュールには、リスト、配列、シーケンス、その他のコレクション型で使用できる関数に対応する関数も含まれています。 次のような関数が含まれます: Option.mapOption.iterOption.forallOption.existsOption.foldBackOption.foldOption.count。 これらの関数を使用すると、要素が 0 または 1 個のコレクションのようにオプションを使用できます。 詳細と例については、「リスト」のコレクション関数の説明を参照してください。

他の型への変換

オプションは、リストまたは配列に変換できます。 オプションをこれらのデータ構造のいずれかに変換すると、結果のデータ構造には 0 個または 1 個の要素が含まれます。 オプションを配列に変換するには、Option.toArray を使用します。 オプションをリストに変換するには、Option.toList を使用します。

関連項目