swift - Los operadores "++" y "-" han quedado en desuso Xcode 7.3
swift2 increment (11)
Estoy mirando las notas de Xcode 7.3 y noto este problema.
Los operadores ++ y - han quedado en desuso
¿Podría alguien explicar por qué está en desuso?
Y estoy en lo cierto en que en la nueva versión de Xcode ahora vas a usar en lugar de
++
este
x += 1
;
Ejemplo:
for var index = 0; index < 3; index += 1 {
print("index is /(index)")
}
Apple ha eliminado el
++
y lo ha simplificado mucho con la otra forma tradicional.
En lugar de
++
, debe escribir
+=
.
Ejemplo:
var x = 1
//Increment
x += 1 //Means x = x + 1
De manera similar para el operador de decremento
--
, necesita escribir
-=
Ejemplo:
var x = 1
//Decrement
x -= 1 //Means x = x - 1
Para bucles:
Ejemplo de incremento:
En vez de
for var index = 0; index < 3; index ++ {
print("index is /(index)")
}
Puedes escribir:
//Example 1
for index in 0..<3 {
print("index is /(index)")
}
//Example 2
for index in 0..<someArray.count {
print("index is /(index)")
}
//Example 3
for index in 0...(someArray.count - 1) {
print("index is /(index)")
}
Ejemplo de decremento:
for var index = 3; index >= 0; --index {
print(index)
}
Puedes escribir:
for index in 3.stride(to: 1, by: -1) {
print(index)
}
//prints 3, 2
for index in 3.stride(through: 1, by: -1) {
print(index)
}
//prints 3, 2, 1
for index in (0 ..< 3).reverse() {
print(index)
}
for index in (0 ... 3).reverse() {
print(index)
}
¡Espero que esto ayude!
Aquí hay una versión genérica de algunos de los códigos publicados hasta ahora. Expresaría las mismas preocupaciones que los demás: es una buena práctica no usarlos en Swift. Estoy de acuerdo en que esto podría ser confuso para quienes lean su código en el futuro.
prefix operator ++
prefix operator --
prefix func ++<T: Numeric> (_ val: inout T) -> T {
val += 1
return val
}
prefix func --<T: Numeric> (_ val: inout T) -> T {
val -= 1
return val
}
postfix operator ++
postfix operator --
postfix func ++<T: Numeric> (_ val: inout T) -> T {
defer { val += 1 }
return val
}
postfix func --<T: Numeric> (_ val: inout T) -> T {
defer { val -= 1 }
return val
}
Esto también se puede escribir como una extensión en el tipo numérico.
Chris Lattner ha ido a la guerra contra ++ y -. Él escribe: “El código que realmente utiliza el valor del resultado de estos operadores a menudo es confuso y sutil para un lector / mantenedor de código. Fomentan el código "demasiado complicado" que puede ser lindo, pero difícil de entender ... Si bien Swift tiene un orden de evaluación bien definido, cualquier código que dependiera de él (como foo (++ a, a ++)) sería indeseable incluso si estaba bien definido ... estos fallan la métrica de "si aún no los tuviéramos, ¿los agregaríamos a Swift 3?"
Apple quería mantener rápido un lenguaje limpio, claro, no confuso y directo al grano. Y así, desaprobaron ++ y - palabra clave.
De los github.com/apple/swift-evolution/blob/master/proposals/… :
Los operadores de incremento / decremento en Swift se agregaron muy temprano en el desarrollo de Swift, como una transferencia de C. Estos se agregaron sin mucha consideración, y no se han pensado mucho desde entonces. Este documento proporciona una nueva mirada a ellos y, en última instancia, recomienda que los eliminemos por completo, ya que son confusos y no tienen su peso.
En Swift 4.1 se podría lograr de esta manera:
prefix operator ++
postfix operator ++
extension Int{
static prefix func ++(x: inout Int)->Int{
x += 1
return x
}
static postfix func ++(x: inout Int)->Int{
x += 1
return x-1
}
}
//example:
var t = 5
var s = t++
print("/(t) /(s)")
Tenga en cuenta que a pesar de que esta solución es similar a las soluciones anteriores en esta publicación, ya no funcionan en Swift 4.1 y este ejemplo sí.
También tenga en cuenta que cualquiera de los anteriores menciona que + = es un reemplazo para ++ simplemente no entiende completamente al operador ya que ++ combinado con la asignación son en realidad dos operaciones, por lo tanto, un acceso directo.
En mi ejemplo:
var s = t++
hace dos cosas: asigna el valor de t a sy luego incrementa t.
Si el ++ viene antes, son las mismas dos operaciones realizadas en orden inverso.
En mi opinión, el razonamiento de Apple sobre por qué eliminar este operador (mencionado en respuestas anteriores) no es solo un razonamiento falso, sino que además creo que es una mentira y la verdadera razón es que no pudieron hacer que su compilador lo maneje.
Les dio problemas en versiones anteriores, por lo que se dieron por vencidos.
La lógica de "operador demasiado complicado de entender, por lo tanto eliminado" es obviamente una mentira porque Swift contiene operadores mucho más complicados y mucho menos útiles que no fueron eliminados.
Además, la gran mayoría de los lenguajes de programación lo tienen.
JavaScript, C, C #, Java, C ++ y muchos más.
Los programadores lo usan felizmente.
Para quienes es demasiado difícil entender este operador, ellos y solo ellos deberían hacer el + = (o tal vez s = s + 1 si + = también es demasiado complejo).
La estrategia detrás de Swift es simple: Apple cree que el programador es tonto y, por lo tanto, debe ser tratado en consecuencia.
La verdad es que Swift, lanzado en septiembre de 2014, se suponía que ya estaría en otro lugar. Otros idiomas crecieron mucho más rápido.
Puedo enumerar muchos errores importantes en el lenguaje, desde serios: como matrices pegadas por valor y no por referencia, hasta molestas: las funciones de parámetros variables no pueden aceptar una matriz, que es toda la idea detrás de esto. No creo que a los empleados de Apple se les permita siquiera mirar otros lenguajes como Java, por lo que ni siquiera saben que Apple está a años luz. Apple podría haber adoptado Java como lenguaje, pero en estos días, el desafío no es la tecnología, sino el ego. Si hubieran abierto IntelliJ para escribir algo de Java, seguramente cerrarían su negocio entendiendo que en este punto, no pueden ponerse al día y nunca lo harán.
Para Swift 4, puede restaurar los operadores
++
y
--
como extensiones para
Int
y otros tipos.
Aquí hay un ejemplo:
extension Int{
static prefix func ++(x: inout Int) -> Int {
x += 1
return x
}
static postfix func ++(x: inout Int) -> Int {
defer {x += 1}
return x
}
static prefix func --(x: inout Int) -> Int {
x -= 1
return x
}
static postfix func --(x: inout Int) -> Int {
defer {x -= 1}
return x
}
}
Funciona de la misma manera para otros tipos, como
UIInt
,
Int8
,
Float
,
Double
, etc.
Puede pegar estas extensiones en un solo archivo en su directorio raíz, y estarán disponibles para su uso dentro de todos sus otros archivos allí.
He notado un par de votos negativos para mi respuesta aquí, casi tan pronto como la publiqué. Lo cual tomo como un desacuerdo filosófico, en lugar de criticar cómo funciona mi código. Funciona perfectamente, si lo revisas en un patio de recreo.
La razón por la que publiqué esta respuesta es porque no estoy de acuerdo con hacer que los lenguajes de programación de computadoras sean innecesariamente diferentes entre sí.
Tener muchas similitudes entre los idiomas hace que sea más fácil para las personas aprender y cambiar de un idioma a otro.
Los desarrolladores normalmente usan varios lenguajes de programación, en lugar de solo uno. Y es una verdadera molestia cambiar de un idioma a otro, cuando no hay convenciones y no hay una estandarización común en todos los idiomas.
Creo que debería haber diferencias de sintaxis entre los idiomas solo tanto como sea necesario, y no más que esto.
Una github.com/apple/swift-evolution/blob/master/proposals/… de Chris Lattner, el creador de Swift. Resumiré los puntos:
- Es otra función que debes aprender mientras aprendes Swift
-
No mucho más corto que
x += 1
- Swift no es C. No debería llevarlos solo para complacer a los programadores de C
-
Su uso principal es en estilo C para loop:
for i = 0; i < n; i++ { ... }
for i = 0; i < n; i++ { ... }
for i = 0; i < n; i++ { ... }
, que Swift tiene mejores alternativas, comofor i in 0..<n { ... }
(el estilo C para el bucle también se está apagando ) -
Puede ser difícil de leer y mantener, por ejemplo, ¿cuál es el valor de
x - ++x
ofoo(++x, x++)
? - A Chris Lattner no le gusta.
Para aquellos interesados (y para evitar la pudrición de enlaces), las razones de Lattner en sus propias palabras son:
Estos operadores aumentan la carga de aprender Swift como primer lenguaje de programación, o cualquier otro caso en el que aún no conozca a estos operadores de un idioma diferente.
Su ventaja expresiva es mínima: x ++ no es mucho más corto que x + = 1.
Swift ya se desvía de C en que el =, + = y otras operaciones similares a asignaciones devuelve Void (por varias razones). Estos operadores son inconsistentes con ese modelo.
Swift tiene características poderosas que eliminan muchas de las razones comunes por las que usaría ++ i en un estilo C para bucle en otros idiomas, por lo que estas se usan con poca frecuencia en un código Swift bien escrito. Estas características incluyen el bucle for-in, rangos, enumeración, mapa, etc.
El código que realmente utiliza el valor del resultado de estos operadores a menudo es confuso y sutil para un lector / mantenedor de código. Alientan el código "demasiado complicado" que puede ser lindo, pero difícil de entender.
Si bien Swift tiene un orden de evaluación bien definido, cualquier código que dependiera de él (como foo (++ a, a ++)) sería indeseable incluso si estuviera bien definido.
Estos operadores son aplicables a relativamente pocos tipos: escalares enteros y de coma flotante, y conceptos similares a iteradores. No se aplican a números complejos, matrices, etc.
Finalmente, estos fallan la métrica de "si aún no los tuviéramos, ¿los agregaríamos a Swift 3?"
i += 1
devuelve
Void
, por lo tanto,
++i
o
i++
devuelve
Void
.
Mantienen el mismo significado.
Por lo tanto, es mejor eliminar "++" y "-", tal como lo hace Python.
Me doy cuenta de que este comentario no responde la pregunta, sin embargo, puede haber personas que busquen una solución para mantener a estos operadores trabajando y tal solución se puede encontrar en la parte inferior. 😇
Personalmente prefiero los operadores
++
y
--
.
No puedo estar de acuerdo con la opinión de que son difíciles o difíciles de manejar.
Una vez que el desarrollador comprende lo que hacen estos operadores (y estamos hablando de cosas bastante simples), el código debe ser muy claro.
En la explicación de por qué los operadores quedaron en desuso se menciona que su uso principal era en estilo C para bucles.
No conozco a los demás, pero personalmente no uso bucles de estilo C en absoluto y todavía hay muchos otros lugares o situaciones en que
++
o
--
operator es útil.
También me gustaría mencionar que
varName++
devuelve un valor para que pueda usarse en el
return
mientras que
varName += 1
no puede.
Para cualquiera de ustedes que deseen mantener a estos operadores trabajando aquí, la solución es:
prefix operator ++ {}
postfix operator ++ {}
prefix operator -- {}
postfix operator -- {}
// Increment
prefix func ++(inout x: Int) -> Int {
x += 1
return x
}
postfix func ++(inout x: Int) -> Int {
x += 1
return (x - 1)
}
prefix func ++(inout x: UInt) -> UInt {
x += 1
return x
}
postfix func ++(inout x: UInt) -> UInt {
x += 1
return (x - 1)
}
prefix func ++(inout x: Int8) -> Int8 {
x += 1
return x
}
postfix func ++(inout x: Int8) -> Int8 {
x += 1
return (x - 1)
}
prefix func ++(inout x: UInt8) -> UInt8 {
x += 1
return x
}
postfix func ++(inout x: UInt8) -> UInt8 {
x += 1
return (x - 1)
}
prefix func ++(inout x: Int16) -> Int16 {
x += 1
return x
}
postfix func ++(inout x: Int16) -> Int16 {
x += 1
return (x - 1)
}
prefix func ++(inout x: UInt16) -> UInt16 {
x += 1
return x
}
postfix func ++(inout x: UInt16) -> UInt16 {
x += 1
return (x - 1)
}
prefix func ++(inout x: Int32) -> Int32 {
x += 1
return x
}
postfix func ++(inout x: Int32) -> Int32 {
x += 1
return (x - 1)
}
prefix func ++(inout x: UInt32) -> UInt32 {
x += 1
return x
}
postfix func ++(inout x: UInt32) -> UInt32 {
x += 1
return (x - 1)
}
prefix func ++(inout x: Int64) -> Int64 {
x += 1
return x
}
postfix func ++(inout x: Int64) -> Int64 {
x += 1
return (x - 1)
}
prefix func ++(inout x: UInt64) -> UInt64 {
x += 1
return x
}
postfix func ++(inout x: UInt64) -> UInt64 {
x += 1
return (x - 1)
}
prefix func ++(inout x: Double) -> Double {
x += 1
return x
}
postfix func ++(inout x: Double) -> Double {
x += 1
return (x - 1)
}
prefix func ++(inout x: Float) -> Float {
x += 1
return x
}
postfix func ++(inout x: Float) -> Float {
x += 1
return (x - 1)
}
prefix func ++(inout x: Float80) -> Float80 {
x += 1
return x
}
postfix func ++(inout x: Float80) -> Float80 {
x += 1
return (x - 1)
}
prefix func ++<T : _Incrementable>(inout i: T) -> T {
i = i.successor()
return i
}
postfix func ++<T : _Incrementable>(inout i: T) -> T {
let y = i
i = i.successor()
return y
}
// Decrement
prefix func --(inout x: Int) -> Int {
x -= 1
return x
}
postfix func --(inout x: Int) -> Int {
x -= 1
return (x + 1)
}
prefix func --(inout x: UInt) -> UInt {
x -= 1
return x
}
postfix func --(inout x: UInt) -> UInt {
x -= 1
return (x + 1)
}
prefix func --(inout x: Int8) -> Int8 {
x -= 1
return x
}
postfix func --(inout x: Int8) -> Int8 {
x -= 1
return (x + 1)
}
prefix func --(inout x: UInt8) -> UInt8 {
x -= 1
return x
}
postfix func --(inout x: UInt8) -> UInt8 {
x -= 1
return (x + 1)
}
prefix func --(inout x: Int16) -> Int16 {
x -= 1
return x
}
postfix func --(inout x: Int16) -> Int16 {
x -= 1
return (x + 1)
}
prefix func --(inout x: UInt16) -> UInt16 {
x -= 1
return x
}
postfix func --(inout x: UInt16) -> UInt16 {
x -= 1
return (x + 1)
}
prefix func --(inout x: Int32) -> Int32 {
x -= 1
return x
}
postfix func --(inout x: Int32) -> Int32 {
x -= 1
return (x + 1)
}
prefix func --(inout x: UInt32) -> UInt32 {
x -= 1
return x
}
postfix func --(inout x: UInt32) -> UInt32 {
x -= 1
return (x + 1)
}
prefix func --(inout x: Int64) -> Int64 {
x -= 1
return x
}
postfix func --(inout x: Int64) -> Int64 {
x -= 1
return (x + 1)
}
prefix func --(inout x: UInt64) -> UInt64 {
x -= 1
return x
}
postfix func --(inout x: UInt64) -> UInt64 {
x -= 1
return (x + 1)
}
prefix func --(inout x: Double) -> Double {
x -= 1
return x
}
postfix func --(inout x: Double) -> Double {
x -= 1
return (x + 1)
}
prefix func --(inout x: Float) -> Float {
x -= 1
return x
}
postfix func --(inout x: Float) -> Float {
x -= 1
return (x + 1)
}
prefix func --(inout x: Float80) -> Float80 {
x -= 1
return x
}
postfix func --(inout x: Float80) -> Float80 {
x -= 1
return (x + 1)
}
prefix func --<T : BidirectionalIndexType>(inout i: T) -> T {
i = i.predecessor()
return i
}
postfix func --<T : BidirectionalIndexType>(inout i: T) -> T {
let y = i
i = i.predecessor()
return y
}
var value : Int = 1
func theOldElegantWay() -> Int{
return value++
}
func theNewFashionWay() -> Int{
let temp = value
value += 1
return temp
}
Esto es definitivamente un inconveniente, ¿verdad?