Swiftの indirect
について調べてみました。
indirect
とは
Swift2.0から登場(正確にはXcode7 β4かららしい)。enumにくっつけて使うと再帰的なenumを作ることができる。
enum Sample {
case Some(Sample) //ここで再帰している
}
と書こうとすると、 indirect enum Sample
にするよう指摘してくれる。 indirect case Some(Sample)
でも可
indirect
の用途
公式ドキュメント的にはThe Swift Programming Language: Enumerationsの
Recursive Enumerations
に書いてある。題材は (5 + 4) * 2
のような Int
と足し算と割り算の3つの要素を enum
を使って表すというもの。
要は enum
と indirect
を使うと二分木とかリストとか作れる
なぜ indirect
とつけなければいけないのか
enum
自体は値型( String
とか Structure
とかの類)で再帰ができないため。らしい。 indirect
が使えないβ3以前で二分木を作ろうとすると、再帰ができないので1つの enum
で表現することができず、複数の enum
を用意する必要がある。
参考:
A persistent tree using indirect enums in Swift | Airspeed Velocity
Swift1.2時代のやり方との比較をされている記事:
http://qiita.com/satoshia/items/9c6465356e2e155cd078
おまけその1: indirect
と sizeof
indirect
で再帰が発生するとサイズがちいさくなる。
enum Sample<T> {
case Foo(T)
case Bar(T)
}
indirect enum Sample1<T> {
case Foo(T)
case Bar(T)
}
enum Sample2<T> {
indirect case Foo(T)
case Bar(T)
}
enum Sample3<T> {
indirect case Foo(T)
indirect case Bar(T)
}
sizeof() | T = Int
|
T = String
|
---|---|---|
Sample | 9 | 25 |
Sample1 | 8 | 8 |
Sample2 | 9 | 25 |
Sample3 | 8 | 8 |
おまけその2: case
バグ
http://qiita.com/satoshia/items/9c6465356e2e155cd078 でも紹介されているが、 if case let hoge = .Some(...) { ... }
といった具合に switch
文以外でcaseを使うとクラッシュするらしい。
β5では解消されている模様