Skip to content

Instantly share code, notes, and snippets.

@ilyannn
Last active August 29, 2015 14:04
Show Gist options
  • Save ilyannn/a4bb096615b7d2baa418 to your computer and use it in GitHub Desktop.
Save ilyannn/a4bb096615b7d2baa418 to your computer and use it in GitHub Desktop.
Enumerating enum values – a universal approach
// This new version seems to be syntactically correct,
// but it crashes together with Xcode as of beta 3.
// (radar link should appear here)
// Find smallest N such that f(N) = nil.
func exhaust<T>(fun: Int -> T?) -> Int {
var index = 0
while fun(index) { index++ }
return index
}
// Everything we can get from a mapping function.
struct Universe<Enum:RawRepresentable where Enum.RawType == Int>: Sequence {
typealias MapType = MapSequenceView<Range<Int>, Enum>
let fun: Int -> Enum?
let count: Int
let keys: Range<Int>
let values:MapType
let pairs: Zip2<Range<Int>, MapType>
init() {
fun = Enum.fromRaw
count = exhaust(fun)
keys = 0..<count
values = map(keys, {Enum.fromRaw($0)!})
pairs = Zip2(keys, values)
}
subscript(raw:Int) -> Enum {
return fun(raw)!
}
func generate() -> ZipGenerator2< RangeGenerator<Int>, MapType.GeneratorType> {
return pairs.generate()
}
}
// Declare enum as usual and a helper structure.
enum Color: Int {
case Red
case Green
case Blue
}
let Colors = Universe<Color>()
// Enjoy.
for (index, color) in Colors {
println("\(index) ⇒ \(color)")
}
for color in Colors.values {
// ...
}
Color.Red == Colors[0]
// Find smallest N such that f(N) = nil.
func exhaust<T>(fun: Int -> T?) -> Int {
var index = 0
while fun(index) { index++ }
return index
}
// Everything we can get from a mapping function.
struct Universe<Enum>: Sequence {
typealias MapType = MapSequenceView<Range<Int>, Enum>
let fun: Int -> Enum?
let count: Int
let keys: Range<Int>
let values:MapType
let pairs: Zip2<Range<Int>, MapType>
init(_ enumf:Int -> Enum?) {
fun = enumf
count = exhaust(fun)
keys = 0..<count
values = map(keys, {enumf($0)!})
pairs = Zip2(keys, values)
}
subscript(raw:Int) -> Enum {
return fun(raw)!
}
func generate() -> ZipGenerator2< RangeGenerator<Int>, MapType.GeneratorType> {
return pairs.generate()
}
}
// Declare enum as usual and a helper structure.
enum Color: Int {
case Red
case Green
case Blue
}
let Colors = Universe(Color.fromRaw)
// Enjoy.
for (index, color) in Colors {
println("\(index) ⇒ \(color)")
}
for color in Colors.values {
// enum values
}
Color.Red == Colors[0] // true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment