エラーハンドリング
Elmが保証してくれる安全性の1つに、ランタイムエラーを実際に見ることはないということがあります。その理由としては Elmはエラーをデータとして扱うということ が挙げられます。エラーが起こってアプリケーション全体がクラッシュするよりは失敗の可能性を明示的にカスタム型を使って表現するほうが好まれます。例えば、ユーザからの入力を年齢に変換したいとしましょう。カスタム型をこのように作りましょう:
type MaybeAge
= Age Int
| InvalidInput
toAge : String -> MaybeAge
toAge userInput =
...
-- toAge "24" == Age 24
-- toAge "99" == Age 99
-- toAge "ZZ" == InvalidInput
toAge
関数にどのような入力が与えられた場合でも常に値を生成します。有効な入力の場合はAge 24
やAge 99
などの値を生成するのに対して、無効な入力の場合はInvalidInput
という値を生成します。それからパターンマッチを使って両方の可能性が確実に処理されるようにします。クラッシュはしません!
こういう問題には常に遭遇します!例えば、他の人と共有するために、ユーザからの大量の入力をPost
型に変換したいとします。しかし、タイトルを入力するのを忘れたらどうなるでしょうか?もしくはその投稿に中身がなかったら?すべての問題を明示的にモデリングしましょう:
type MaybePost
= Post { title : String, content : String }
| NoTitle
| NoContent
toPost : String -> String -> MaybePost
toPost title content =
...
-- toPost "hi" "sup?" == Post { title = "hi", content = "sup?" }
-- toPost "" "" == NoTitle
-- toPost "hi" "" == NoContent
入力が無効であるというだけではなく、入力がどう間違っているかをそれぞれ表現しています。有効な投稿をプレビューするためのviewPreview:MaybePost -> Html msg
関数があれば、何か問題が発生したときにプレビュー領域にもっと具体的なエラーメッセージを表示できるようになります!
このような状況は極めて一般的です。その場その場に合わせてカスタム型を作成したほうがしばしば有益ですが、より単純な場合には代わりに既製の型を使用することができます。それでこの章の残りの部分ではMaybe
型とResult
型を新たに学び、この2つの型がどのようにエラーをデータとして扱うのを助けることができるかを示します!