This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public enum Suit { | |
Spades, Hearts, Diamonds, Clubs; | |
} | |
for (Suit suit : Suit.values()) { | |
System.out.println(suit.toString()); | |
} |
なぜかSwiftのenum型はそのままではイテレーションすることができません。対策としてGeneratorという仕組みが標準ライブラリに用意されてますので、それを使ってenumをイテレーションできるようにします。
具体的には、Generatorを継承したクラスを作成して next() -> Element? を実装してください。ElementはAnyObjectのtypealiasなので実際には好きな型を返していただければOKです。あとはSequenceOf<T>型でGeneratorをラップしてあげればOKです。next()メソッドがnilを返すまでSequenceOf<T>はイテレーションを続けてくれます。
以下にサンプルコードを示します。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum Rank:Int { | |
case Ace = 1 | |
case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten | |
case Jack, Queen, King | |
// Here's an undocumented trick: How to enumerate enums using Generator! | |
// I wish I could use yield though ;( | |
class EnumGenerator:Generator { | |
var i = 1 | |
func next() -> Rank? { | |
let e = Rank.fromRaw(i) | |
i++ | |
return e | |
} | |
} | |
static func enumerate() -> SequenceOf<Rank> { | |
return SequenceOf<Rank>({EnumGenerator()}) | |
} | |
} | |
enum Suit:String { | |
case Spades = "Spades" | |
case Hearts = "Hearts" | |
case Diamonds = "Diamonds" | |
case Clubs = "Clubs" | |
class EnumGenerator:Generator { | |
var current:Suit? = Suit.Spades | |
func next() -> Suit? { | |
let e = self.current | |
if let c = self.current { | |
switch c { | |
case .Spades: | |
self.current = Suit.Hearts | |
case .Hearts: | |
self.current = Suit.Diamonds | |
case .Diamonds: | |
self.current = Suit.Clubs | |
default: | |
self.current = nil | |
} | |
} | |
return e | |
} | |
} | |
static func enumerate() -> SequenceOf<Suit> { | |
return SequenceOf<Suit>({EnumGenerator()}) | |
} | |
} | |
struct Card { | |
var rank:Rank | |
var suit:Suit | |
static func fullSetOfCards()->Array<Card> { | |
var result = Array<Card>() | |
for suit in Suit.enumerate() { | |
for rank in Rank.enumerate() { | |
let card = Card(rank: rank, suit: suit) | |
result.append(card) | |
} | |
} | |
return result | |
} | |
} | |
let deck = Card.fullSetOfCards() |
Generator内部でyieldが使えれば便利なんですが、おそらくyield構文は無さそうです。Enum型を一覧したい場合以外にもGeneratorは便利に使えますのでぜひお試しください。