Search code examples
cocoaswiftswift-extensions

Extending Bool for fun and new control structures in Swift


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?


Solution

  • 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!