[Swift] Swift の Result

Swift

     

TAGS:

⌛️ < 1 min.

100DaysOfSwiftUIでResultを学習しました。

ちょっと面白そうだったので、もう少し調べてみました。

Resultの定義

Resultそのものは、なんとenumです!

enum Result where Failure : Error

上記は、
「Resultは、任意の型SuccessとErrorプロトコルに適合したFailureというタイプを使います。」ということです。

ちなみに、Errorプロトコルと書かれていますが、このプロトコルが要求するものは、なにも無いです。

便利な点その1:OK/NG判定が定型的になる

成功/エラーの判定が画一的にできることが、便利な点となります。これまでは、返り値が、nilだったり、errorがnon-nilだったりといろいろとあり、きちんと確認しなければいけませんでしたが、このResult型が返されるとすると、エラー処理についても定型的に処理できることになります。(もちろん、処理内容はケースバイケースです)
具体的には、このResultを、switch対象とすると、case として、 .success と .failure の2つしかあり得ないことを保証されていることで、エラー判定が非常にシンプルになります。

switch result {
case .success(let str):
    print(str)
case .failure(let error):
    switch error {
    case .Error1:
        print("error1")
    case .Error2:
        print("error2")
    }
}

Swiftでのswitch文は、全ケースを網羅していないとエラーとなりますが、上記は、.successと.failureを列挙しているだけでOKとなります。
# PlayGround等で試してみるとわかります。

返り値とerrorの値の組み合わせを考慮する必要がなくなるのは、読みやすいコードに繋がりますよね。

便利な点その2:エラーの内容を網羅的にチェックできる

上記でサンプルとして挙げたコードのErrorは、自分で以下のように定義していました。

enum MyError: Error {
    case Error1, Error2
}

自分が定義していればという前提付きとなりますが、エラーのパターンとして、上記で列挙したものしか返ってこないことが保証されます。
Swiftのswitch文を使うことで、きちんと全てのエラーケースをチェックしているかどうかを言語的にチェックすることが可能となります
上記の.failure節を見てもらうとわかりますが、.Error1と.Error2を列挙していないと、コンパイルエラーとなります。

便利な点その3:OKケースでの結果取得

普通に結果を取得するには、throw-ableメソッドのgetを使います。tryを使って実行しなければいけないという意味です。

ですが、上記の.successの中では、結果の存在が保証されているので、.success(let resultValue)というような形で結果を変数に受けることができます。その後の処理がうまくいくことをswitch文の実行で保証されるので、非常にスマートに記述できている感じがします。

機会があればResultを使おう

上で見てもらったように、Resultをきちんと使うことで、if let … や guard let … と同様の防御的な実装が可能となります。
全ての関数の返り値にResultを使うべきかというとそうではないと思いますが、複雑な処理、特に非同期処理の実装には、便利だと思います。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です