如何检测 swift 中 IteratorProtocol 的第一个 运行?
How to detect the first run of an IteratorProtocol in swift?
正在尝试检测 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)))
以上代码可以做哪些修改来检测第一个运行?
逐字回答您的问题:您可以添加一个布尔变量
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()
正在尝试检测 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)))
以上代码可以做哪些修改来检测第一个运行?
逐字回答您的问题:您可以添加一个布尔变量
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()