在Swift中扩展Bool以获得有趣和新的控制结构

时间:2014-09-15 20:38:59

标签: cocoa swift swift-extensions

我正在玩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之后,循环也会继续打开。

有关可能发生的事情的任何想法?

2 个答案:

答案 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和尾随块语法之上,似乎在语言中添加了新的语句类型