かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

手軽なスクリプト言語としてのF# その18「オプション型」

さて、今回は小ネタです。小ネタだけど要所要所でお世話になるオプション型というものを紹介したいと思います。オプション型というのは値がある場合と無い場合があるという状態を表したいときに使います。C#とかでは一般的にnullが使われるような状態で使われるものですね。

たとえば以下のようなケースです。

int? GetValue(int i)
{
  return i % 2 == 0 ? null : i;
}

処理としては意味ないですが偶数だとnullを返して奇数だとそのまま数字を返すような処理です。これをF#のoptionを使って書き直してみます。

// 偶数だったらNone 奇数だったらSome iを返す
let getValue i =
    if i % 2 = 0 then None
    else Some i

// 呼び出してみる
printfn "%A" <| getValue 2
printfn "%A" <| getValue 3

opetion型は何も値がないNoneと何か値を持つSome 値 という2パターンを持ちます。Someの後には任意の値を渡すことができます。
次に、option型から値を取得したりする方法を見てみようと思います。option型にはIsSome, IsNone, Valueといったプロパティが定義されているので、これらのプロパティを使って値を取得したりできます。
(ただ、このプロパティを使って値をとるとかいうことは、本当はあまりしないけど、それは次の回あたりで説明します)

// 任意の型のoptionを受け取ってプロパティの値を表示する
let printOption (v : 'a option) =
    printfn "IsSome = %A" v.IsSome
    printfn "IsNone = %A" v.IsNone
    printfn "Value = %A" v.Value

// 二種類のoptionを用意して
let v1 = Some "Hello"
let v2 = None

// 状態を表示してみる
printOption v1
printOption v2

実行結果は以下のようになります。

IsSome = true
IsNone = false
Value = "Hello"
IsSome = false
IsNone = true
System.NullReferenceException: オブジェクト参照がオブジェクト インスタンスに設定されていません。
   場所 FSI_0001.printOption[a](FSharpOption`1 v) 場所 hoge.fsx:行 4
   場所 <StartupCode$FSI_0001>.$FSI_0001.main@() 場所 hoge.fsx:行 10

最後がNullReferenceExceptionになっていますが、これはNoneに対してValueを呼び出すと起きてしまいます。なのでNoneから値はどう頑張っても取得できません。

Option型は、結果が成功するか失敗するかよくわからない関数の戻り値によく使われています。C#とかだとnullだったりしますが、nullより安全?なoption型がF#ではデファクトみたいです。
なので、よくお世話になる型なので覚えておきましょう。そして、本当はもっと便利に使える方法もあるので、それについて次回説明したいと思います。