Swift Quickie: MirrorType Extension
edit: the Mirror
struct now has a children
property that you can indeed iterate over so this isn't really applicable anymore but the sequence stuff is still relevant. You can check out Rob Napier's post about AnySequence for more info.
I've been playing with the new reflection API in Swift 2 and found one constant annoyance: MirrorType
is not a Sequence
so you can't write the natural for child in mirror
pattern.
Fortunately we can fix that with a protocol extension:
extension MirrorType {
func children() -> AnySequence<(String, MirrorType)> {
let c = self.count
var index = 0
return AnySequence({
return anyGenerator({
if index >= c {
return nil
}
return self[index++]
})
})
}
}
And now:
for (label, childMirror) in mirror.children() {
print(label)
}
Hurrah! Also if you were wondering how to create anonymous generators or sequences now that GeneratorOf
and SequenceOf
are gone... now you know.
But again there's some boilerplate that really annoys me. Perhaps we can borrow the anyGenerator
function idea and create anySequence
:
func anySequence<T>(generatorBody: () -> T?) -> AnySequence<T> {
return AnySequence(anyGenerator { generatorBody() })
}
//one-liner sequences!
let infiniteOnes = anySequence { 1 }
Now apply that to the previous MirrorType
extension:
extension MirrorType {
func children() -> AnySequence<(String, MirrorType)> {
var index = 0
return anySequence { index >= self.count ? nil : self[index++] }
}
}
Much better. Each call of children()
creates a new environment that anySequence
captures. That anonymous environment holds the state of the generator. If you're curious check out AnySequence<T>
, AnyGenerator<T>
, and the anyGenerator()
functions.
This blog represents my own personal opinion and is not endorsed by my employer.