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では解消されている模様