switchSwift'teki ifadelere aşinayım , ancak bu kod parçasının nasıl değiştirileceğini merak ediyorum switch:
if someVar < 0 {
// do something
} else if someVar == 0 {
// do something else
} else if someVar > 0 {
// etc
}
switchSwift'teki ifadelere aşinayım , ancak bu kod parçasının nasıl değiştirileceğini merak ediyorum switch:
if someVar < 0 {
// do something
} else if someVar == 0 {
// do something else
} else if someVar > 0 {
// etc
}
Yanıtlar:
İşte bir yaklaşım. someVarBir Intveya başka olduğunu varsayarsak , Comparableisteğe bağlı olarak işleneni yeni bir değişkene atayabilirsiniz. Bu, whereanahtar kelimeyi kullanarak istediğiniz şekilde kapsamlamanızı sağlar :
var someVar = 3
switch someVar {
case let x where x < 0:
print("x is \(x)")
case let x where x == 0:
print("x is \(x)")
case let x where x > 0:
print("x is \(x)")
default:
print("this is impossible")
}
Bu biraz basitleştirilebilir:
switch someVar {
case _ where someVar < 0:
print("someVar is \(someVar)")
case 0:
print("someVar is 0")
case _ where someVar > 0:
print("someVar is \(someVar)")
default:
print("this is impossible")
}
whereAnahtar kelime aralığını aralık eşleme ile de tamamen önleyebilirsiniz :
switch someVar {
case Int.min..<0:
print("someVar is \(someVar)")
case 0:
print("someVar is 0")
default:
print("someVar is \(someVar)")
}
default: fatalError()Olası mantık hatalarını erken tespit etmenizi öneririm .
assertionFailure, özellikle bir ekipte çalışırken daha güvenli bir seçenek gibi görünüyor.
Swift 5 ile if ifadenizi değiştirmek için aşağıdaki anahtarlardan birini seçebilirsiniz.
PartialRangeFromve ile anahtarın kullanılmasıPartialRangeUpTolet value = 1
switch value {
case 1...:
print("greater than zero")
case 0:
print("zero")
case ..<0:
print("less than zero")
default:
fatalError()
}
ClosedRangeve ile anahtarın kullanılmasıRangelet value = 1
switch value {
case 1 ... Int.max:
print("greater than zero")
case Int.min ..< 0:
print("less than zero")
case 0:
print("zero")
default:
fatalError()
}
let value = 1
switch value {
case let val where val > 0:
print("\(val) is greater than zero")
case let val where val == 0:
print("\(val) is zero")
case let val where val < 0:
print("\(val) is less than zero")
default:
fatalError()
}
_let value = 1
switch value {
case _ where value > 0:
print("greater than zero")
case _ where value == 0:
print("zero")
case _ where value < 0:
print("less than zero")
default:
fatalError()
}
RangeExpressionProtokol ~=(_:_:)operatörüyle anahtar kullanmalet value = 1
switch true {
case 1... ~= value:
print("greater than zero")
case ..<0 ~= value:
print("less than zero")
default:
print("zero")
}
EquatableProtokol ~=(_:_:)operatörüyle anahtar kullanmalet value = 1
switch true {
case value > 0:
print("greater than zero")
case value < 0:
print("less than zero")
case 0 ~= value:
print("zero")
default:
fatalError()
}
PartialRangeFrom, PartialRangeUpTove RangeExpressions' contains(_:)yöntemilet value = 1
switch true {
case (1...).contains(value):
print("greater than zero")
case (..<0).contains(value):
print("less than zero")
default:
print("zero")
}
0.1ölümcül bir hata atar 1.... Bu nedenle, bu çözüm yalnızca bir ise çalışır value, Intancak bu tehlikelidir çünkü değişken türü değişirse işlevsellik herhangi bir derleyici hatası olmadan kesilir.
switchAçıklamada, kaputun altında kullanır ~=operatörü. Yani bu:
let x = 2
switch x {
case 1: print(1)
case 2: print(2)
case 3..<5: print(3..<5)
default: break
}
Desugars:
if 1 ~= x { print(1) }
else if 2 ~= x { print(2) }
else if 3..<5 ~= x { print(3..<5) }
else { }
Standart kütüphane referansına bakarsanız, tam olarak ne ~=yapılması gerektiğini söyleyebilir : dahil edilen aralık eşleme ve eşitlikli şeyler için eşitleme. (Std lib'deki bir işlev yerine bir dil özelliği olan enum-case eşleşmesi dahil değildir)
Sol tarafta düz bir boole ile eşleşmediğini göreceksiniz. Bu tür karşılaştırmalar için bir where ifadesi eklemeniz gerekir.
Tabii ... ~=operatörü kendiniz aşırı yüklemezseniz. (Bu genellikle edilir değil Bir olasılık böyle bir şey olacağını önerilir):
func ~= <T> (lhs: T -> Bool, rhs: T) -> Bool {
return lhs(rhs)
}
Bu, soldaki bir boolean'ı sağdaki parametresine döndüren bir işlevle eşleşir. İşte bunun için kullanabileceğiniz bir şey:
func isEven(n: Int) -> Bool { return n % 2 == 0 }
switch 2 {
case isEven: print("Even!")
default: print("Odd!")
}
Durumunuz için aşağıdaki gibi bir ifadeniz olabilir:
switch someVar {
case isNegative: ...
case 0: ...
case isPositive: ...
}
Ama şimdi yeni isNegativeveisPositive işlevleri . Daha fazla operatör yüklemediğiniz sürece ...
Kıvrımlı önek veya düzeltme sonrası operatörleri olarak normal infix operatörlerini aşırı yükleyebilirsiniz. İşte bir örnek:
postfix operator < {}
postfix func < <T : Comparable>(lhs: T)(_ rhs: T) -> Bool {
return lhs < rhs
}
Bu şöyle çalışır:
let isGreaterThanFive = 5<
isGreaterThanFive(6) // true
isGreaterThanFive(5) // false
Bunu önceki işlevle birleştirdiğinizde, switch ifadeniz şöyle görünebilir:
switch someVar {
case 0< : print("Bigger than 0")
case 0 : print("0")
default : print("Less than 0")
}
Şimdi, muhtemelen bu tür şeyleri pratikte kullanmamalısınız: biraz tehlikeli. (Muhtemelen) whereifadeye sadık kalsan iyi olur . Bununla birlikte,
switch x {
case negative:
case 0:
case positive:
}
veya
switch x {
case lessThan(someNumber):
case someNumber:
case greaterThan(someNumber):
}
Dikkate değer olması için yeterince yaygın görünüyor.
Birisi zaten gönderdi yana case let x where x < 0:burada yer için bir alternatiftir someVarbir olduğunu Int.
switch someVar{
case Int.min...0: // do something
case 0: // do something
default: // do something
}
Ve işte someVara nerede olduğu için bir alternatif Double:
case -(Double.infinity)...0: // do something
// etc
Aralıklarla böyle görünüyor
switch average {
case 0..<40: //greater or equal than 0 and less than 40
return "T"
case 40..<55: //greater or equal than 40 and less than 55
return "D"
case 55..<70: //greater or equal than 55 and less than 70
return "P"
case 70..<80: //greater or equal than 70 and less than 80
return "A"
case 80..<90: //greater or equal than 80 and less than 90
return "E"
case 90...100: //greater or equal than 90 and less or equal than 100
return "O"
default:
return "Z"
}
<0İfadesi (artık?) İş değil bu ile sona erdi böylece:
Swift 3.0:
switch someVar {
case 0:
// it's zero
case 0 ..< .greatestFiniteMagnitude:
// it's greater than zero
default:
// it's less than zero
}
X_MAXalmıştır .greatestFiniteMagnitude, yani Double.greatestFiniteMagnitude, CGFloat.greatestFiniteMagnitudevb Yani genellikle, sadece yapabileceği case 0..< .greatestFiniteMagnitudetürüne beri someVarzaten bilinmektedir
var timeLeft = 100 switch timeLeft {case 0...<=7200: print("ok") default:print("nothing") }neden <=tanınmıyor? Eğer eşit olmadan yazarsam işe yarar. Teşekkürler
case 0...7200:Operatör <=bir karşılaştırma operatörüdür. Bir anahtarda yalnızca menzil operatörlerini kullanabilirsiniz (bkz. Dokümanlar)
someVarşeydi Intve bazı yapmak zorunda Double(kaldımVar) `` çalışması için ...
Swift 4'ün bu sorunu çözdüğüne sevindim:
3'te bir çözüm olarak:
switch translation.x {
case 0..<200:
print(translation.x, slideLimit)
case -200..<0:
print(translation.x, slideLimit)
default:
break
}
Çalışıyor ama ideal değil