かずきのBlog@hatena

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

手軽なスクリプト言語としてのF# その26「例外」

fparsecというパーサに手を出してみましたが、まだ力不足で使いこなせる気がしなかったので基本に戻ってきました。今日は悲しいかな例外です。
例外は、C#の例外と同じものだと思ってもらってOKだと思います。私はそう思ってます。F#での例外の定義の仕方は、とても簡単です。

exception 型名 of タプル

みたいな感じで定義できます。試しに例外作って投げてみましょう。投げるにはraise関数を使います。

// 例外定義して
exception Error1 of string

// 投げるだけ
raise (Error1("だめぽ"))

必ず例外が出るので見慣れたスタックフローが表示されます。

ハンドルされていない例外: Program+Error1: 種類 'Program+Error1' の例外がスローさ
れました。
   場所 Microsoft.FSharp.Core.Operators.Raise[T](Exception exn)
   場所 <StartupCode$ConsoleApplication29>.$Program.main@() 場所 c:\users\kazuki
\documents\visual studio 2010\Projects\ConsoleApplication29\ConsoleApplication29
\Program.fs:行 6

因みに、例外は投げたからにはキャッチするのが王道です。F#での例外のキャッチにはtry with文を使います。withの部分でパターンマッチで例外を判別します。

// 例外定義して
exception Error1 of string

try
    // 投げるだけ
    raise (Error1("だめぽ"))
with
    | Error1 (s) -> printfn "%s" s

例外に複数の情報を持たせたかったらタプルなのでいくつでも増やすことが出来ます。試しに2つに増やしてみます。

// 例外定義して
exception Error1 of string * int

try
    // 投げるだけ
    raise (Error1("だめぽ", 1))
with
    // 普通にパターンマッチできる
    | Error1 (s, 0) -> printfn "0: %s" s
    | Error1 (s, 1) -> printfn "1: %s" s
1: だめぽ

次に.NET Frameworkの例外も捕まえてみようと思います。皆大好きNullReferenceExceptionを投げてみます。キャッチのほうは変数名を書くだけでキャッチ出来ます。

open System

try
    // 投げるだけ
    raise (NullReferenceException("ぬるり"))
with
    // 変数に入れてキャッチ
    | e -> printfn "%s" e.Message

型指定でキャッチする例外を仕分けすることもできます。

open System

try
    // 投げるだけ
    raise (NullReferenceException("ぬるり"))
with
    // 型名でパターンマッチできる
    | :? ArgumentException as e -> printfn "引数だめよ"
    | :? NullReferenceException as e -> printfn "%s" e.Message

いい感じ。キャッチした例外の再スローはreraiseという関数があるのでこれを使うのがいいらしいです。


そして最後にfinallyです。これは何故こうなったのか謎で仕方ないのですがtry withとは別物扱いなので例外時も通常時も最後に固定の処理をやりたいという要件のときにはtry withをtry finallyで囲わないといけません。

open System

try
    try
        // 投げるだけ
        raise (NullReferenceException("ぬるり"))
    with
        // 型名でパターンマッチできる
        | :? ArgumentException as e -> printfn "引数だめよ"
        | :? NullReferenceException as e -> printfn "%s" e.Message
finally
    printfn "ふぁいなりー"

ちょっとめんどくさいですね・・・実行するとふぁいなりーの処理が走ってるのがわかります。

ぬるり
ふぁいなりー


おおざっぱには説明しましたが、細かい所をもっと勉強したいという人はMSDNをあたるのが一番です。

failwithやinvalidArg関数の使い方とかは、ここではやってないのでMSDNの例を見てみるのがいいと思います(力尽きた)

過去記事