例えばこんな感じの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]
をループするのかの差もあるのかと(予想だけど)。