Read
序列
一个序列 (sequence) 代表的是一系列具有相同类型 的值,你可以对这些值进行迭代。遍历一个序列最简单的方式是使用 for 循环:
1 |
for element in someSequence { |
满足 Sequence 协议的要求十分简单,你需要做的所有事情就是提供一个返回迭代器 (iterator) 的 makeIterator() 方法:
1 |
protocol Sequence { |
迭代器
序列通过创建一个迭代器来提供对元素的访问。迭代器每次产生一个序列的值,并且当遍历序 列时对遍历状态进行管理。在 IteratorProtocol 协议中唯一的一个方法是 next(),这个方法需 要在每次被调用时返回序列中的下一个值。当序列被耗尽时,next() 应该返回 nil:
我们一般不管心迭代器是如何工作的, 除非你自定义一个序列类型的时候需要。for 循环在背后: 编译器会自动为序列生成一个迭代器, 并且不断的调用 next 方法, 直到返回 nil。
1 |
var iterator = someSequence.makeIterator() while let element = iterator.next() { |
迭代器是单向结构,它只能按照增加的方向前进,而不能倒退或者重置。虽然大部分的迭代器 的 next() 都只产生有限数量的元素,并最终会返回 nil,但是你也完全可以创建一个无限的,永 不枯竭的序列。实际上,除了那种一上来就返回 nil 的迭代器,最简单的情况应该是一个不断返 回同样值的迭代器了:
1 |
struct ConstantIterator: IteratorProtocol { |
typealias 其实不需要写, 这里为了代码的可读性好, 就写出来了。 其实 next 的返回值可以推断出 Element 的类型为 Int。
注意这里 next() 被标记为了 mutating。对于我们这个简单的例子来说,我们的迭代器不包含任 何可变状态,所以它并不是必须的。不过在实践中,迭代器的本质是存在状态的。几乎所有有 意义的迭代器都会要求可变状态,这样它们才能够管理在序列中的当前位置。
我们来看一个更有意义的例子。FibsIterator 迭代器可以产生一个斐波那契序列。它将记录接
下来的两个数字,并作为状态存储,next 函数做的事情是为接下来的调用更新这个状态,并且 返回第一个数。和之前的例子一样,这个迭代器也将产生 “无穷” 的数字,它将持续累加数字, 直到程序因为所得到的数字发生类型溢出而崩溃 (我们暂时先不考虑这个问题):
遵守序列协议
我们也可以创造有限序列的迭代器,比如下面这个 Pre