使用辅助函数(最初定义于将使用除法作为步骤的 C 风格 for 循环转换为 Swift 3)
public func sequence<T>(first: T, while condition: @escaping (T)-> Bool, next: @escaping (T) -> T) -> UnfoldSequence<T, T> {
let nextState = { (state: inout T) -> T? in
// Return `nil` if condition is no longer satisfied:
guard condition(state) else { return nil }
// Update current value _after_ returning from this call:
defer { state = next(state) }
// Return current value:
return state
}
return sequence(state: first, next: nextState)
}
你可以将循环写为
let num = 1000
for i in sequence(first: 5, while: { num/$0 > 0 }, next: { $0 * 5 }) {
print(i)
}
一个更简单的解决方案是 while 循环:
var i = 5
while num/i > 0 {
print(i)
i *= 5
}
但第一种方案的优点是循环变量的作用域仅限于循环体,并且循环变量是一个常量。
斯威夫特3.1将提供一个prefix(while:)序列方法,
然后辅助函数就不再需要了:
let num = 1000
for i in sequence(first: 5, next: { $0 * 5 }).prefix(while: { num/$0 > 0 }) {
print(i)
}
所有上述解决方案都“等效于”给定的 C 循环。However,如果出现以下情况,它们都会崩溃num
接近Int.max
and $0 * 5
溢出。如果这是一个问题,那么你必须检查
如果$0 * 5
适合整数范围before做乘法。
实际上,这使得循环更简单——至少如果我们假设num >= 5
以便循环至少执行一次:
for i in sequence(first: 5, next: { $0 <= num/5 ? $0 * 5 : nil }) {
print(i)
}