Swift的for...in
可以用在所有实现了SequenceType
的类型上,而为了实现SequenceType
你首先需要实现一个GeneratorType
。比如一个实现了反向generator
和Sequence
可以这么写
protocol GeneratorType {
associatedtype Element
func next() -> Element?
}
// 先定义一个实现了 GeneratorType protocol 的类型
// GeneratorType 需要执行一个 typealias Element
// 以及提供一个返回 Element? 的方法 next()
class ReverseGenerator: GeneratorType {
typealias Element = Int
var counter: Element
init<T>(array: [T]) {
self.counter = array.count - 1
}
init(start: Int) {
self.counter = start
}
func next() -> Element? {
if self.counter < 0 {
return nil
} else {
let count = self.counter
self.counter -= 1
return count
}
}
}
protocol SequenceType {
associatedtype Generator
func generate() -> Generator?
}
// 然后我们来定义 SequenceType
// 和 GeneratorType 很类似,不过换成指定一个 typealias Generator
// 以及提供一个返回 Generator? 的方法 generate()
struct ReverseSequence<T>: SequenceType {
var array: [T]
init(array: [T]) {
self.array = array
}
typealias Generator = ReverseGenerator
func generate() -> ReverseGenerator? {
return ReverseGenerator(array: array)
}
}
如果我们想要探究 for…in 这样的方法到底做了什么的话,我们将其展开,大概会是下面这样
let arr = [0, 1, 2, 3, 4]
var array = ReverseSequence(array: arr)
var g = array.generate()
while let obj = g.next() {
if obj == nil {
return
}
print(obj)
}
顺便你可以免费得到的收益是你可以使用想map
、filter
和reduce
这些方法,因为它们都有对应SequenceType
的版本
protocol SequenceType {
typealias Generator = ReverseGenerator
func map<S : SequenceType, T>(source: S, transform: (S.Generator.Element) -> T) -> T
func filter<S : SequenceType>(source: S, includeElement: (S.Generator.Element) -> Bool) -> [S.Generator.Element]
func reduce<S : SequenceType, U>(sequence: S, initial: U, combine: (U, S.Generator.Element) -> U) -> U
}