Swift 5.9 ha llegado cargado de nuevas características que prometen revolucionar la forma en que escribimos y mantenemos nuestro código. En esta entrada, exploraremos algunas de las novedades más destacadas y veremos cómo pueden mejorar tu flujo de trabajo.
1. If y switch como expresiones:SE-0380
Por fin una tan esperada novedad: ahora podemos usar condicionales if y switch como expresiones para obtener un resultado. Esto ayuda a reducir la sintaxis y obtener un código más limpio:
let score = 800
let simpleResult = if score > 500 { "Pass" } else { "Fail" }
print(simpleResult)
let complexResult = switch score {
case ...300: "Fail"
case 301...500: "Pass"
case 501...800: "Merit"
default: "Distinction"
}
print(complexResult)
No es obligatorio asignar el resultado a variable alguna; también puede ser retornado directamente de funciones/métodos:
func rating(for score: Int) -> String {
switch score {
case ...300: "Fail"
case 301...500: "Pass"
case 501...800: "Merit"
default: "Distinction"
}
}
print(rating(for: score))
Podrías pensar que esto es semejante al operador ternario y si que es similar en la mayoria de los casos. Pero hay un echo curioso cuando se utiliza el operador ternario o el if. Mire este código:
let customerRating = 4
let bonusMultiplier1 = customerRating > 3 ? 1.5 : 1
let bonusMultiplier2 = if customerRating > 3 { 1.5 } else { 1 } //<= Error!!
Si compilamos este código, Swift no estará muy contento con la última línea. Esto sucede porque cuando utilizamos el operador ternario ambos valores se evaluan conjuntamente y se infiere que son de tipo Double. Mientras que si utilizamos if la inferencia falla porque los valores son evaluados distintamente, y por tanto, Swift infiere que se trata de un Double(1.5) y un Int(1) lo cual no es aceptable. Para corregir este error, basta con poner el valor 1.0 en la opción alternativa del if.
2. Paquetes de parámetros de tipo y valor: (SE-0393 , SE-0398 y SE-0399)
Se ha combinado tres propuestas para englobar un conjunto de mejoras que permite el uso de parámetros genéricos variádicos.
Uno de los problemas que resuelve es que ahora es posible especificar una cantidad indeterminada de parámetros. Estas funciones podian seguir aceptando parámetros variádicos pero tenian que ser del mismo tipo. Dar un ejemplo e intentar explicarlo queda fuera del alcance de este post. Por ello, si quieres saber más sobre esta nueva y poderosa característica pueden leer esta artículo de Hacking with Swift.
3. Macros: (SE-0382 , SE-0389 y SE-0397)
De nuevo se han combinado tres propuestas para agregar una poderosa y muy útil novedad en Swift 5.9: La Creación de Macros. Una Macro es un recurso que permite crear código que transforma la sintaxis en tiempo de compilación. Una macro expande código y ayuda a eliminar el código repetitivo. Si desea saber más sobre este tema eche un vistaso a este post de Paul Hudson.
4.Estructuras y enumeraciones No Copiables: SE-0390
Esta novedad introduce un nuevo concepto de estructura y enumeración no copiable. Esto significa que se puede compartir una única instacia de una estructura o enumeración y compartirse en muchos lugares. En última instacia sigue teniendo un propietario pero ahora se puede acceder a ellas en varios lugares del código.
Para crear una estructura no copiable Swift introduce una nueva sintaxis ~Copyable:
struct User: ~Copyable {
var name: String
}
Observación: Los tipo no copiables no pueden ajustarse a ningún protocolo que no sea Sendable.
func createUser() {
let newUser = User(name: "Anonymous")
var userCopy = newUser
print(userCopy.name)
}
createUser()
Hay otras cuestiones sobre esta nueva característica. Puede leer este post si desea más información.
5. Operador consume para terminar el ciclo de vida de una variable binding: SE-0366
Con esta novedad se extiende el concepto de consumir valores a variables locales y constantes de tipo copiables. Esto puede ayudar a liberar recursos y retenciones que se producen al copiar los valores.
Por ejemplo:
struct User{
var name : String
}
func createUser(){
let newUser = User(name:"Yorj")
let copyUser = consume newUser
print(copyUser.name)
//Error! la variable newUser ha sido consumida. Se ha liberado el recurso
print(newUser.name)
}
Esto crea una instancia de la estructura User en la variable newUser. Después se hace una copia de dicha variable con la palabra consume por lo que su asignación en memoria se libera. El nuevo operador consume solo funciona sobre variables locales y parámetros de funciones.
Si desea saber más sobre esta noveda consulte este post.
6. Método AsyncStream.makeStream de conveniencia: SE-0388
Adiciona un método makeStream() a AsyncStream y a AsyncThrowingStream para enviar la secuencia conjuntamente con su continuación. Veamos un ejemplo:
//Antes:
var _continuation: AsyncStream.Continuation!
let stream = AsyncStream { _continuation = $0 }
let continuation = _continuation!
//Ahora:
let (newStream, newContinuation) = AsyncStream.makeStream(of: String.self)
Si lo desea puedes conocer más sobre esto con el excelente post de Paul Hudson.
7. Adición del método sleep(for:) al protocolo Clock: SE-0374
Este nuevo método permite suspender la ejecución durante una cantidad determinada de segundo. También extiende la suspensión de Task para una tolerancia específica.
Por ejemplo:
try await Task.sleep(for: .seconds(1), tolerance: .seconds(0.5))
8. Descartar grupos de tareas: SE-0381
Agrega nuevos grupos de tareas descartables, las cuales se terminan automáticamente una vez que son completadas, sin el uso de Next(). Estos nuevos grupos de tareas descartables se crean con las funciones:withDiscardingTaskGroup() y withThrowingDiscardingTaskGroup()
Para más información puede leler este post.
Otras Novedades Destacadas
- Mejoras en el depurador: El depurador de Swift ahora es más rápido y confiable.
- Interoperabilidad con C++: Swift 5.9 mejora la interoperabilidad con C++, lo que permite integrar código Swift en proyectos C++ y viceversa.
Conclusión
Swift 5.9 es una versión repleta de novedades que hacen que el desarrollo de aplicaciones sea más eficiente y divertido. Los macros, las variádicas genéricas y las mejoras en el manejo de errores son solo algunas de las características que vale la pena explorar.
Gracias por leer, si le ha parecido útil este post puede dejarme un comentario. Feliz codificación!