switch
Swift'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
}
switch
Swift'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. someVar
Bir Int
veya başka olduğunu varsayarsak , Comparable
isteğe bağlı olarak işleneni yeni bir değişkene atayabilirsiniz. Bu, where
anahtar 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")
}
where
Anahtar 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.
PartialRangeFrom
ve ile anahtarın kullanılmasıPartialRangeUpTo
let value = 1
switch value {
case 1...:
print("greater than zero")
case 0:
print("zero")
case ..<0:
print("less than zero")
default:
fatalError()
}
ClosedRange
ve ile anahtarın kullanılmasıRange
let 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()
}
RangeExpression
Protokol ~=(_:_:)
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")
}
Equatable
Protokol ~=(_:_:)
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
, PartialRangeUpTo
ve RangeExpression
s' 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
, Int
ancak bu tehlikelidir çünkü değişken türü değişirse işlevsellik herhangi bir derleyici hatası olmadan kesilir.
switch
Açı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 isNegative
veisPositive
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) where
ifadeye 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 someVar
bir olduğunu Int
.
switch someVar{
case Int.min...0: // do something
case 0: // do something
default: // do something
}
Ve işte someVar
a 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_MAX
almıştır .greatestFiniteMagnitude
, yani Double.greatestFiniteMagnitude
, CGFloat.greatestFiniteMagnitude
vb Yani genellikle, sadece yapabileceği case 0..< .greatestFiniteMagnitude
türüne beri someVar
zaten 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 Int
ve 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