しおメモ

雑多な技術系ブログです。

SwiftでRustのようなResult型を実装する

Swiftで従来のthrow~catchでは書きづらい場面も多々あるので、
RustのResult型を参考にした、エラーハンドルを取り入れてみました。

やること

SwiftでRustのResult型のような、直和型の返り値を使ったエラーハンドルを実現する。

std::result::Result - Rust

実装

enumを使って直和型であることを表現します。
Genericsとassociated valueで、結果(型T)かエラー(型E)のどちらかの値を持つ状態を表現します。

case

Rustに倣って、okerrorの2つのcaseを持ちます。

enum Result<T, E> {
    case ok(T)
    case error(E)
}

switch文で、okの場合とerrorの場合の処理を記述することができます。

メソッド

ok, errorの場合のみ処理を書きたい時のために、Optionalで返すメソッドを用意します。

func ok() -> T? {
    switch self {
    case .ok(let result):
        return result
    case .error:
        return nil
    }
}

func error() -> E? {
    switch self {
    case .ok:
        return nil
    case .error(let error):
        return error
    }
}

その他

例えば、mapなどの実装はこのようになります。

func map<U>(_ transform: ((T) -> U)) -> Result<U, E> {
    switch self {
    case .ok(let result):
        return .ok(transform(result)) as Result<U, E>
    case .error(let error):
        return .error(error) as Result<U, E>
    }
}

使い方

switchで使う

typealias Res = Result<Int, String>
let someResult: Res = .ok(1)

switch someResult {
case .ok(let result):
    print(result)
case .error(let error):
    print(error)
}

Optionalで使う

if let result = someResult.ok() {
    print(result)
}

サンプル

ここにあります。

github.com