17
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

エラーの時にOptional型を返すのはよくない

Last updated at Posted at 2015-01-01

SwiftにはOptional型がありますが、エラーの時にOptional型を返すと、エラーの情報を返せないのでよくないと思っています。どんな実装でもいいのでEither的な型を使いましょう。

すでに様々な実装がありますが、私も作ってみました。まだインターフェイスを固定したくないのでCarthageやCocoaPodsには対応してませんが、デファクトなものがなければこれで行くつもりでいます。

使い方はREADME#SYNOPSISのとおりです。

Either Chaining

optional chainingに相当するchain()メソッドと、null coalescing operatorに相当するfallback()メソッドがあります。

成功状態を返すsuccess()と、失敗状態とエラー情報を返すfailure()があるとして、chain()は以下のように使います。

// 最初の値が成功状態であれば、chain()のブロックを実行してその値を返す
success("success").chain({ (m) -> Either<String, Error> in
    return success("chained")
}) // success("chained")

// 最初の値が失敗状態であれば、最初の値をそのまま返す
// エラー情報をそのまま持っているので正しくエラーハンドリングが可能
failure("error!").chain({ (m) -> Either<String, Error> in
    return Either(success: "chained")
}) // "error!"

Fallback Operation

null coalescing operatorに相当するのはfallback()メソッドです。エイリアスとして「??」演算子もあります。

// 最初の値が成功状態であれば、それをそのまま返す
success("success").fallback({
    return success("chained")
}) // "success"

// 最初の値が失敗状態であれば、fallback()の引数ブロックを実行してその値を返す
// つまり、ある値が失敗したら次の演算にフォールバックする
failure("error!").fallback({
    return success("fallback")
}) // "fallback"

// 演算子のほうが挙動はわかりやすいかも
failure("error!") ?? success("fallback") // success("fallback")

// 演算子の右辺値は生の値でもよい
failure("error!") ?? "fallback" // success("fallback")

Unwrapping

Optional型のようにoptional bindingはありませんが、switchによるパターンマッチで同じことができます。実際、optional bindingはパターンマッチの糖衣構文にすぎません。

switch success("foo") {
case .Success(let s):
    // 成功状態の場合
    // sは参照型のコンテナなので値を得るには.valueが必要
    s.value // "foo"
case .Failure(let f):
    // 失敗状態の場合
    // f.valueはError型
    f.value.reason // not reached
}

successValueとfailureValueがそれぞれOptional型を返すので、入っている値が確定しているならそれでもかまいません。

(success("foo").successValue)! == "foo" // true
(failure("foo").failureValue)! == "foo" // true

捕捉

Swiftにはタプルがあるので、エラーを返すときにgolangのように (T?, Error?) というタプルを返すこともできます。しかし、これは戻り値をOptional型にせざるをえません。Optional型はエラー情報を持たないEither型とも考えられるため、それならば結局Either的なものを返すほうがシンプルでいいと思います。

17
16
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?