I'm playing around with Swift extensions, and bumped my head against a strange bug, while trying to extend Bool:
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.")
}
For some reason the loop just goes on and on, even after the boolean
expression has become true
.
Any ideas of what might be going on?
The issue is that the expression i < 1
will be evaluated once, resulting in false
. It will not be continually re-evaluated. To achieve this you would have to replace it with a function or closure.
If you really want to, you could re-write your code as follows:
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.")
}
But that is pretty darn ugly!