我可以在 Swift 中创建一个生成器吗?
使用迭代器,我需要存储中间结果,例如:
struct Countdown: IteratorProtocol, Sequence {
private var value = 0
init(start: Int) {
self.value = start
}
mutating func next() -> Int? {
let nextNumber = value - 1
if nextNumber < 0 {
return nil
}
value -= 1
return nextNumber
}
}
for i in Countdown(start: 3) {
print(i)
} // print 1 2 3
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我需要存储value.
在我的情况下,我想使用生成器而不是迭代器,因为我不想将序列的中间结果存储在每个next.
从 Python 开始,理解生成器的工作原理(以及为什么它们在 swift 中不那么重要)是很困难的。
在 Swift v2.1 之前,有一个名为 GeneratorType 的协议。这在 Swift v3.0+ 中更名为 IteratorProtocol。你可以遵循这个协议来创建你自己的对象,这些对象可以像在 Python 中所做的那样进行即时计算。
更多信息可以在 Apple 文档中找到:IteratorProtocol
IteratorProtocol 页面的一个简单示例:
struct CountdownIterator: IteratorProtocol {
let countdown: Countdown
var times = 0
init(_ countdown: Countdown) {
self.countdown = countdown
}
mutating func next() -> Int? {
let nextNumber = countdown.start - times
guard nextNumber > 0
else { return nil }
times += 1
return nextNumber
}
}
let threeTwoOne = Countdown(start: 3)
for count in threeTwoOne {
print("\(count)...")
}
// Prints "3..."
// Prints "2..."
// Prints "1..."
Run Code Online (Sandbox Code Playgroud)
但是,您需要考虑为什么要使用生成器:
Swift 会自动执行“写入时复制”的操作。这意味着许多使用 Python 生成器来避免对象集合(数组、列表、字典等)的大量复制成本的情况在 Swift 中是不必要的。您可以通过使用使用写入时复制的类型之一免费获得此功能。
也可以使用包装器强制几乎所有对象在写入时进行复制,即使它不是集合的一部分:
swift 中的优化通常意味着您不必编写生成器。如果您确实需要(通常是因为数据量大,科学计算),则可以如上所述。
| 归档时间: |
|
| 查看次数: |
6483 次 |
| 最近记录: |