例えばこんな感じのenumを定義して
enum Fruit: Int {
case Apple
case Orange
case Banana
}
この全ての列挙子(ここではAppleとOrangeとBanana)をfor inを使って列挙したくなったとする。どう考えてもfor fruit in [Fruit.Apple, Fruit.Orange, Fruit.Banana]なんてしたくない。
GeneratorOfを使って[Fruit]を返す
たどり着いたのがGeneratorOfを使って動的に[Fruit]を返すプロパティを生やすやり方。
enum Fruit: Int {
case Apple
case Orange
case Banana
static var fruits: [Fruit] {
var index = 0
return Array(
GeneratorOf<Fruit> {
return Fruit(rawValue: index++)
}
)
}
}
for fruit in Fruit.fruits {
println(fruit)
}
これはこれで覚えておくとして、もっとスマートなやり方があるのかないのか。というか、言語機能として列挙子返してくれないのかしら。
SequenceOfを使ってSequenceOf<Fruit>を返す
@satoshia さんのコメントより、こちらはSequenceOfを使ってSequenceOf<Fruit>を返却している。
static var fruits: SequenceOf<Fruit> {
return SequenceOf { () -> GeneratorOf<Fruit> in
var index = 0
return GeneratorOf {
Fruit(rawValue: index++)
}
}
}
配列を生成しない分スマートに見える。配列ではなくSequenceOf<Fruit>だけど、forで列挙する分には何ら問題ない。
自前で初期化して[Fruit]を返す
@takabosoft さんのコメントより。
static let fruits3: [Fruit] = [.Apple, .Orange, .Grape, .Berry, .Banana]
簡単だし、わかりやすいし、動的じゃない分パフォーマンスも良さそう。その反面、列挙漏れ・enumの宣言順が反映されない・追加や削除の度に更新しなくてはならないというリスクもある。とはいえ、列挙子の数が少なければこれでも良いような気も。
パフォーマンスの比較
予想通りの結果になった。SequenceOfがGeneratorOfより若干遅いのは、配列を生成するしないに加えて、SequenceOf<Fruit>をループするのか[Fruit]をループするのかの差もあるのかと(予想だけど)。
