Расширение 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.
Какие-нибудь идеи о том, что может происходить?
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