3

我正在玩 Swift 扩展,并在尝试扩展 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.")
}

出于某种原因,即使在boolean表达式变成true.

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

4

2 回答 2

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

但这实在是太丑了!

于 2014-09-15T20:44:15.693 回答
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.")
}

它建立在自动关闭和尾随块语法的基础上,似乎为语言添加了一种新的语句类型

于 2014-09-15T22:40:02.330 回答