Skip to content

Instantly share code, notes, and snippets.

@rickpasveer
Forked from kristopherjohnson/enumerateEnum.swift
Last active July 7, 2016 09:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rickpasveer/ab4d3d538082796d68af8b47a14f388d to your computer and use it in GitHub Desktop.
Save rickpasveer/ab4d3d538082796d68af8b47a14f388d to your computer and use it in GitHub Desktop.
Helper functions for enumerating values of a Swift enum
protocol ConvertibleFromRawInt {
static func fromRaw(raw: Int) -> Self?
}
// Note: Tried to use Swift's standard RawRepresentable protocol rather
// than ConvertibleFromRawInt, but couldn't get it to compile.
// Don't know whether it is a Swift bug or something I was doing wrong.
// Generator for a sequence of contiguous ConvertibleFromRawInt values
class ConvertibleFromRawIntGenerator<T: ConvertibleFromRawInt>: GeneratorType {
typealias Element = T
var nextRawValue: Int
init(firstRawValue: Int) {
nextRawValue = firstRawValue
}
func next() -> T? {
return T.fromRaw(nextRawValue++)
}
}
// Generator for a sequence of ConvertibleFromRawIntValues bounded by low and high raw values
class ConvertibleFromRawIntRangeGenerator<T: ConvertibleFromRawInt>: GeneratorType {
typealias Element = T
var nextRawValue: Int
var lastRawValue: Int
init(firstRawValue: Int, lastRawValue: Int) {
self.nextRawValue = firstRawValue
self.lastRawValue = lastRawValue
}
init(range: Range<Int>) {
self.nextRawValue = range.startIndex
self.lastRawValue = range.endIndex - 1
}
func next() -> T? {
if (nextRawValue <= lastRawValue) {
return T.fromRaw(nextRawValue++)
}
else {
return nil
}
}
}
// Given the first raw value of a ConvertibleFromRawInt type, generate values until fromRaw() returns nil
func enumerateFromRawValue<T: ConvertibleFromRawInt>(firstRawValue: Int) -> AnySequence<T> {
return AnySequence<T>({ ConvertibleFromRawIntGenerator(firstRawValue: firstRawValue) })
}
// Given first and last raw values of a range of valid raw values for a ConvertibleFromRawType type, generate a sequence of corresponding values
func enumerate<T: ConvertibleFromRawInt>(firstRawValue: Int, lastRawValue: Int) -> AnySequence<T> {
return AnySequence<T>({ ConvertibleFromRawIntRangeGenerator(firstRawValue: firstRawValue, lastRawValue: lastRawValue) })
}
// Given a range of valid raw values for a ConvertibleFromRawType type, generate a sequence of corresponding values
func enumerate<T: ConvertibleFromRawInt>(range: Range<Int>) -> AnySequence<T> {
return AnySequence<T>({ ConvertibleFromRawIntRangeGenerator(range: range) })
}
// Examples
enum Suit: Int {
case Clubs, Diamonds, Hearts, Spades
}
extension Suit: CustomStringConvertible {
var description: String {
switch (self) {
case .Clubs: return "Clubs"
case .Diamonds: return "Diamonds"
case .Hearts: return "Hearts"
case .Spades: return "Spades"
}
}
}
// Enumerate all the suits
extension Suit: ConvertibleFromRawInt {
static func enumerate() -> AnySequence<Suit> {
return enumerateFromRawValue(Suit.Clubs.rawValue)
}
static func fromRaw(raw: Int) -> Suit? {
return Suit(rawValue: raw)
}
}
for suit in Suit.enumerate() {
print("\(suit.description) = \(suit.rawValue)\n")
}
/* Output:
Clubs = 0
Diamonds = 1
Hearts = 2
Spades = 3
*/
enum Rank: Int {
case Wild = 0
case Two = 2, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace
}
extension Rank: CustomStringConvertible {
var description: String {
switch (self) {
case .Two: return "Two"
case .Three: return "Three"
case .Four: return "Four"
case .Five: return "Five"
case .Six: return "Six"
case .Seven: return "Seven"
case .Eight: return "Eight"
case .Nine: return "Nine"
case .Ten: return "Ten"
case .Jack: return "Jack"
case .Queen: return "Queen"
case .King: return "King"
case .Ace: return "Ace"
default: return "(Rank \(self.rawValue))"
}
}
}
// Enumerate all the Ranks, skipping over "Wild"
extension Rank: ConvertibleFromRawInt {
// Enumerate rank values [ Two, Three, ..., King, Ace ]
static func enumerate() -> AnySequence<Rank> {
return enumerateFromRawValue(Rank.Two.rawValue)
}
static func fromRaw(raw: Int) -> Rank? {
return Rank(rawValue: raw)
}
}
for rank in Rank.enumerate() {
print("\(rank.description) = \(rank.rawValue)\n")
}
/* Output
Two = 2
Three = 3
Four = 4
Five = 5
Six = 6
Seven = 7
Eight = 8
Nine = 9
Ten = 10
Jack = 11
Queen = 12
King = 13
Ace = 14
*/
// Enumerate the face cards
let faceCardRange = Rank.Jack.rawValue...Rank.King.rawValue
let faceCards: AnySequence<Rank> = enumerate(faceCardRange)
for faceCard in faceCards {
print("Face card: \(faceCard.description) = \(faceCard.rawValue)\n")
}
/* Output
Face card: Jack = 11
Face card: Queen = 12
Face card: King = 13
*/
@rickpasveer
Copy link
Author

updated for swift 2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment