尝试检测Iterator协议的首次运行。 在下面的示例中,我尝试从零开始打印斐波那契数列,但从一开始:
class FibIterator : IteratorProtocol {
var (a, b) = (0, 1)
func next() -> Int? {
(a, b) = (b, a + b)
return a
}
}
let fibs = AnySequence{FibIterator()}
print(Array(fibs.prefix(10)))
可以对上述代码进行哪些修改以检测首次运行?
答案 0 :(得分:1)
要回答您的逐字记录问题:您可以添加一个布尔变量
firstRun
来检测next()
方法的第一次调用:
class FibIterator : IteratorProtocol {
var firstRun = true
var (a, b) = (0, 1)
func next() -> Int? {
if firstRun {
firstRun = false
return 0
}
(a, b) = (b, a + b)
return a
}
}
let fibs = AnySequence { FibIterator() }
print(Array(fibs.prefix(10))) // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
但是对于此问题有更完善的解决方案。
您可以“推迟”对a
和b
的更新,在返回后
当前值:
class FibIterator : IteratorProtocol {
var (a, b) = (0, 1)
func next() -> Int? {
defer { (a, b) = (b, a + b) }
return a
}
}
let fibs = AnySequence { FibIterator() }
print(Array(fibs.prefix(10))) // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
或-也许更简单-更改初始值(使用事实 斐波那契数也为负数定义)
class FibIterator : IteratorProtocol {
var (a, b) = (1, 0) // (Fib(-1), Fib(0))
func next() -> Int? {
(a, b) = (b, a + b)
return a
}
}
let fibs = AnySequence { FibIterator() }
print(Array(fibs.prefix(10))) // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
请注意,如果您声明符合Sequence
协议
那么您就不需要AnySequence
包装器了(默认情况下
makeIterator()
的实现符合类型
IteratorProtocol
)。值类型通常也是首选,
因此-除非需要引用语义-您可以将其设置为struct
:
struct FibSequence : Sequence, IteratorProtocol {
var (a, b) = (1, 0) // (Fib(-1), Fib(0))
mutating func next() -> Int? {
(a, b) = (b, a + b)
return a
}
}
let fibs = FibSequence()