for - uiswitch swift
Menor o mayor que en la declaración de cambio rápido (8)
Estoy familiarizado con las declaraciones de
switch
en Swift, pero me pregunto cómo reemplazar este fragmento de código con un
switch
:
if someVar < 0 {
// do something
} else if someVar == 0 {
// do something else
} else if someVar > 0 {
// etc
}
Aquí hay un enfoque.
Suponiendo que
someVar
es un
Int
u otro
Comparable
, puede asignar opcionalmente el operando a una nueva variable.
Esto le permite abarcarlo como quiera usando la palabra clave
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")
}
Esto se puede simplificar un poco:
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")
}
También puede evitar la palabra clave
where
completo con la coincidencia de rango:
switch someVar {
case Int.min..<0:
print("someVar is /(someVar)")
case 0:
print("someVar is 0")
default:
print("someVar is /(someVar)")
}
Así es como se ve con los rangos
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"
}
Con Swift 5, puede elegir uno de los siguientes interruptores para reemplazar su declaración if.
# 1 Usando el interruptor con
PartialRangeFrom
y
PartialRangeUpTo
let value = 1
switch value {
case 1...:
print("greater than zero")
case 0:
print("zero")
case ..<0:
print("less than zero")
default:
fatalError()
}
# 2 Usando el interruptor con
ClosedRange
y
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()
}
# 3 Usando el interruptor con la cláusula where
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()
}
# 4 Uso de switch con cláusula where y asignación a
_
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()
}
# 5 Uso del interruptor con el
RangeExpression
~=(_:_:)
del protocolo
RangeExpression
let value = 1
switch true {
case 1... ~= value:
print("greater than zero")
case ..<0 ~= value:
print("less than zero")
default:
print("zero")
}
# 6 Usando el interruptor con el
Equatable
~=(_:_:)
del protocolo
Equatable
let 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()
}
# 7 Usando el interruptor con
PartialRangeFrom
,
PartialRangeUpTo
y
RangeExpression
''s
contains(_:)
método
contains(_:)
let value = 1
switch true {
case (1...).contains(value):
print("greater than zero")
case (..<0).contains(value):
print("less than zero")
default:
print("zero")
}
Dado que alguien ya ha publicado el
case let x where x < 0:
aquí hay una alternativa para donde
someVar
es un
Int
.
switch someVar{
case Int.min...0: // do something
case 0: // do something
default: // do something
}
Y aquí hay una alternativa para donde
someVar
es un
Double
:
case -(Double.infinity)...0: // do something
// etc
La expresión
<0
no funciona (¿ya?), Así que terminé con esto:
Swift 3.0:
switch someVar {
case 0:
// it''s zero
case 0 ..< .greatestFiniteMagnitude:
// it''s greater than zero
default:
// it''s less than zero
}
La instrucción
switch
, debajo del capó, usa el operador
~=
.
Así que esto:
let x = 2
switch x {
case 1: print(1)
case 2: print(2)
case 3..<5: print(3..<5)
default: break
}
Desugar a esto:
if 1 ~= x { print(1) }
else if 2 ~= x { print(2) }
else if 3..<5 ~= x { print(3..<5) }
else { }
Si nos fijamos en la referencia de la biblioteca estándar, puede decirle exactamente para qué está sobrecargado el
~=
: se incluye la coincidencia de rango y la ecuación para cosas equiparables.
(No se incluye la coincidencia de mayúsculas y minúsculas, que es una característica del lenguaje, en lugar de una función en la biblioteca estándar)
Verá que no coincide con un booleano recto en el lado izquierdo. Para ese tipo de comparaciones, debe agregar una declaración where.
A menos que ... sobrecargues el operador
~=
tú mismo.
(Esto generalmente
no se
recomienda) Una posibilidad sería algo como esto:
func ~= <T> (lhs: T -> Bool, rhs: T) -> Bool {
return lhs(rhs)
}
De modo que coincide con una función que devuelve un valor booleano a la izquierda a su parámetro a la derecha. Este es el tipo de cosas para las que podría usarlo:
func isEven(n: Int) -> Bool { return n % 2 == 0 }
switch 2 {
case isEven: print("Even!")
default: print("Odd!")
}
Para su caso, es posible que tenga una declaración que se vea así:
switch someVar {
case isNegative: ...
case 0: ...
case isPositive: ...
}
Pero ahora debe definir las nuevas funciones
isNegative
e
isPositive
.
A menos que sobrecargue algunos operadores más ...
Puede sobrecargar los operadores de infijo normales para ser operadores de prefijo o postfix curry. Aquí hay un ejemplo:
postfix operator < {}
postfix func < <T : Comparable>(lhs: T)(_ rhs: T) -> Bool {
return lhs < rhs
}
Esto funcionaría así:
let isGreaterThanFive = 5<
isGreaterThanFive(6) // true
isGreaterThanFive(5) // false
Combine eso con la función anterior, y su declaración de cambio puede verse así:
switch someVar {
case 0< : print("Bigger than 0")
case 0 : print("0")
default : print("Less than 0")
}
Ahora, probablemente no deberías usar este tipo de cosas en la práctica: es un poco dudoso.
Es (probablemente) mejor seguir con la declaración
where
.
Dicho esto, el patrón de declaración de cambio de
switch x {
case negative:
case 0:
case positive:
}
o
switch x {
case lessThan(someNumber):
case someNumber:
case greaterThan(someNumber):
}
Parece lo suficientemente común como para que valga la pena considerarlo.
Me alegro de que Swift 4 aborde el problema: como solución en 3 hice:
switch translation.x {
case 0..<200:
print(translation.x, slideLimit)
case -200..<0:
print(translation.x, slideLimit)
default:
break
}
Funciona pero no es ideal
Usted puede:
switch true {
case someVar < 0:
print("less than zero")
case someVar == 0:
print("eq 0")
default:
print("otherwise")
}