Я знаком с операторами switch
в Swift, но задаюсь вопросом, как заменить этот кусок кода на switch
:
if someVar < 0 {
// do something
} else if someVar == 0 {
// do something else
} else if someVar > 0 {
// etc
}
Я знаком с операторами switch
в Swift, но задаюсь вопросом, как заменить этот кусок кода на switch
:
if someVar < 0 {
// do something
} else if someVar == 0 {
// do something else
} else if someVar > 0 {
// etc
}
Здесь один подход. Предполагая, что someVar
является Int
или другим Comparable
, вы можете при желании назначить операнд новой переменной. Это позволяет вам охватить его, но вы хотите использовать ключевое слово where
:
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")
}
Это можно немного упростить:
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
с помощью соответствия диапазонов:
switch someVar {
case Int.min..<0:
print("someVar is \(someVar)")
case 0:
print("someVar is 0")
default:
print("someVar is \(someVar)")
}
С помощью Swift 4 вы можете выбрать один из следующих переключателей, чтобы заменить инструкцию if.
CountablePartialRangeFrom
и PartialRangeUpTo
let value = 1
switch value {
case 1...:
print("greater than zero")
case 0:
print("zero")
case ..<0:
print("less than zero")
default:
fatalError()
}
CountableClosedRange
, CountableRange
, Int
max
статическим свойством и Int
min
статическим свойством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
протоколом ~=(_:_:)
operatorlet value = 1
switch true {
case 1... ~= value:
print("greater than zero")
case ..<0 ~= value:
print("less than zero")
default:
print("zero")
}
Equatable
протоколом ~=(_:_:)
operatorlet 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()
}
CountablePartialRangeFrom
, PartialRangeUpTo
и RangeExpression
contains(_:)
methodlet value = 1
switch true {
case (1...).contains(value):
print("greater than zero")
case (..<0).contains(value):
print("less than zero")
default:
print("zero")
}
Оператор switch
, под капотом, использует оператор ~=
. Итак:
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 { }
Если вы посмотрите на стандартную ссылку на библиотеку, она может точно указать, что перегружает ~=
: включено соответствие диапазонов и приравнивание для равнозначные вещи. (Не включено совпадение в виде перечисления, которое является языковой функцией, а не функцией в std lib)
Вы увидите, что он не соответствует прямому логическому полю с левой стороны. Для такого рода сравнений вам нужно добавить оператор where.
Если... вы перегружаете оператор ~=
самостоятельно. (Обычно это не рекомендуется). Одна из возможностей может быть примерно такой:
func ~= <T> (lhs: T -> Bool, rhs: T) -> Bool {
return lhs(rhs)
}
Таким образом, это соответствует функции, которая возвращает логическое значение слева по отношению к его параметру справа. Вот что вы могли бы использовать для:
func isEven(n: Int) -> Bool { return n % 2 == 0 }
switch 2 {
case isEven: print("Even!")
default: print("Odd!")
}
В вашем случае у вас может быть инструкция, которая выглядит так:
switch someVar {
case isNegative: ...
case 0: ...
case isPositive: ...
}
Но теперь вам нужно определить новые функции isNegative
и isPositive
. Если вы не перегрузите еще несколько операторов...
Вы можете перегружать нормальные операторы infix, чтобы быть префиксными или постфиксными операторами. Вот пример:
postfix operator < {}
postfix func < <T : Comparable>(lhs: T)(_ rhs: T) -> Bool {
return lhs < rhs
}
Это будет работать следующим образом:
let isGreaterThanFive = 5<
isGreaterThanFive(6) // true
isGreaterThanFive(5) // false
Объедините это с более ранней функцией, и ваш оператор switch может выглядеть так:
switch someVar {
case 0< : print("Bigger than 0")
case 0 : print("0")
default : print("Less than 0")
}
Теперь вы, вероятно, не должны использовать такие вещи на практике: это немного изворотливое. Вы, вероятно, лучше придерживаетесь утверждения where
. Тем не менее, шаблон оператора switch
switch x {
case negative:
case 0:
case positive:
}
или
switch x {
case lessThan(someNumber):
case someNumber:
case greaterThan(someNumber):
}
Кажется достаточно общим, чтобы его можно было рассмотреть.
Вы можете:
switch true {
case someVar < 0:
print("less than zero")
case someVar == 0:
print("eq 0")
default:
print("otherwise")
}
Поскольку кто-то уже отправил case let x where x < 0:
, здесь есть альтернатива, где someVar
- Int
.
switch someVar{
case Int.min...0: // do something
case 0: // do something
default: // do something
}
И вот альтернатива, где someVar
есть Double
:
case -(Double.infinity)...0: // do something
// etc
Вот как это выглядит с диапазонами
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
не работает (больше?), поэтому я закончил с этим:
Swift 3.0:
switch someVar {
case 0:
// it zero
case 0 ..< .greatestFiniteMagnitude:
// it greater than zero
default:
// it less than zero
}
Рад, что Swift 4 решает проблему: В качестве обходного пути в 3 я сделал:
switch translation.x {
case 0..<200:
print(translation.x, slideLimit)
case -200..<0:
print(translation.x, slideLimit)
default:
break
}
Работает, но не идеально