Extending Bool for Entertainment and New Control Structures in Swift

I'm playing around with the Swift extension and stumbled upon a strange error 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 expression boolean

has become true

.

Any ideas on what might be going on?

+3


source to share


2 answers


The problem is that the expression i < 1

will be evaluated once, the result will be false

. It will not be constantly reviewed. To achieve this, you will have to replace it with a function or a closure.

If you really want to, you can rewrite your code like this:



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's pretty damn ugly!

+3


source


In the same direction as Colin's expression, but building it with auto-closure, you can use:

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.")
}

      

This simplifies things a bit. Of course, the natural syntax would be to just use something like:



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.")
}

      

Which builds on the autoclosure and trailing block syntax to appear to add a new type of statement to the language

+3


source







All Articles