Расширение Bool для развлечения и новые структуры управления в 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.



Какие-нибудь идеи о том, что может происходить?

589   2  

2 ответов:

Проблема заключается в том, что выражение 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.")
}

Но это чертовски некрасиво!

По тем же линиям, что и выражение Колина, но основываясь на нем с автоматическим закрытием, вы можете использовать:

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

, который строится на синтаксисе автоклавирования и завершающего блока, чтобы, казалось бы, добавить новый тип оператора в язык

Comments

    Ничего не найдено.