我正在玩Swift扩展程序,并试图扩展Bool时碰到了一个奇怪的bug:
typealias Task = ()->()
extension Bool{
func untilFalse(task: Task){
while !self {println(self); task()}
}
}
var i = 2
(i < 1).untilFalse{
println(i)
println("\(i) bottles of beer on the wall, \(i) bottles of beer.")
i--
println("Take one down and pass it around, \(i) bottles of beer on the wall.")
}
由于某种原因,即使在boolean
表达式变为true
之后,循环也会继续打开。
有关可能发生的事情的任何想法?
答案 0 :(得分:3)
问题是表达式i < 1
将被评估一次,从而产生false
。它不会被不断重新评估。要实现这一点,您必须使用函数或闭包替换它。
如果您真的想要,可以按如下方式重新编写代码:
typealias Task = ()->()
typealias BooleanExpression = () -> Bool
infix operator *** {}
func *** (b: BooleanExpression, t: Task) {
while !b() { t() }
}
var i = 2
let exp: BooleanExpression = { i < 1 }
exp *** {
println(i)
println("\(i) bottles of beer on the wall, \(i) bottles of beer.")
i--
println("Take one down and pass it around, \(i) bottles of beer on the wall.")
}
但这非常难看!
答案 1 :(得分:3)
与Colin的表达方式相同,但是使用自动关闭构建它,您可以使用:
typealias Task = ()->()
infix operator *** {}
func ***(expression:@autoclosure ()->Bool, task:Task) {
while !expression() {
task()
}
}
var i = 2
(i < 1) *** {
println(i)
println("\(i) bottles of beer on the wall, \(i) bottles of beer.")
i--
println("Take one down and pass it around, \(i) bottles of beer on the wall.")
}
这简化了一些事情。当然,自然语法只是使用类似的东西:
func untilFalse(expression:@autoclosure ()->Bool, block:()->()) {
while(!expression()) {
block()
}
}
var i = 2
untilFalse(i < 1) {
println("\(i) bottles of beer on the wall, \(i) bottles of beer.")
i--
println("Take one down and pass it around, \(i) bottles of beer on the wall.")
}
构建于autoclosure和尾随块语法之上,似乎在语言中添加了新的语句类型