LoginSignup
22
22

More than 5 years have passed since last update.

SwiftのenumでEitherを作る方法

Last updated at Posted at 2014-12-13

(2015.09.08 追記) Swift 2.0 ではこんなことをしなくても Either を作ることができるようになっています。 Either について詳しくはこちら

(2014.12.13 追記) ここに書いた方法は遅延評価の影響でクロージャにキャプチャされた変数が変更された時などに問題がありました。思い付きで書くと良くないですね。イミュータブルな世界なら問題ないのですが。

僕の思い付くミュータブルな世界でも使えるワークアラウンドは↓みたいな感じです。

enum Either<T, U> {
    case Left(Container<T>)
    case Right(Container<U>)

    static func left(left:T) -> Either<T, U> {
        return .Left(Container<T>(left))
    }

    static func right(right:U) -> Either<T, U> {
        return .Right(Container<U>(right))
    }
}

class Container<T> {
    let value: T
    init(_ value: T) {
        self.value = value
    }
}


let either1 = Either<Int, String>.left(123)
let either2 = Either<Int, String>.right("abc")

switch either1 {
case .Left(let integer):
    println(integer.value)
case .Right(let string):
    println(string.value)
}


Swift の enumAssociated Value を使って Tagged Union のようなことができるので、次のような型を作りたくなります。

enum Either<T, U> {
    case Left(T)
    case Right(U)
}

しかし、 Swift 1.1 時点では次のようなコンパイルエラーになってしまいます。

Unimplemented IR generation feature non-fixed multi-payload enum layout

これを回避して同じようなことをやるには @autoclosure を使うことができます。クロージャに包めば参照型になるのでサイズが固定されます。 Java でプリミティブ型をボクシングするのと似てます。

enum Either<T, U> {
    case Left(@autoclosure () -> T)
    case Right(@autoclosure () -> U)
}

@autoclosure は値を渡せば勝手にクロージャに変換してくれる機能です。上記の Either はクロージャの存在を気にせず次のように使えます。

let either1 = Either<Int, String>.Left(123)
let either2 = Either<Int, String>.Right("abc")

ただし、値にアクセスするときはコールして戻り値を得なければなりません。

switch either1 {
case .Left(let integer):
    println(integer()) // ここでコールのための () が必要
case .Right(let string):
    println(string()) // ここでコールのための () が必要
}

@autoclosure の逆のような () なしでアクセスするとコールした戻り値が得られる Attribute があればいいんですけどね(その場合どうやって関数オブジェクトをとればいいんだという話はありますが。でもそれって PropertySubscript も同じ?)。

@autoclosure を使うのは有名な話なのかもしれませんが、ちょっと思い付いたので小ネタとして書いてみました。

22
22
0

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
22
22