かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

手軽なスクリプト言語としての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#ではデファクトみたいです。
なので、よくお世話になる型なので覚えておきましょう。そして、本当はもっと便利に使える方法もあるので、それについて次回説明したいと思います。