Swift es el sucesor de Objective-C, y su diseño se puede resumir en una frase: tomar todo lo que la investigación en lenguajes había demostrado y meterlo en un lenguaje que millones de personas iban a usar el mes siguiente. Tipos algebraicos, opcionales, inmutabilidad por defecto y concurrencia estructurada — con la interfaz gráfica de Apple detrás.
🎯 Por qué está en este programa
Swift es un primo de la familia móvil / moderno (Atlas), junto a Dart, y desciende directamente de Objective-C.
Aporta al programa la gestión de memoria por conteo automático de referencias sin recolector (clase 131), con el problema de los ciclos a la vista; y la concurrencia estructurada con actores integrados en el sistema de tipos (clases 133 y 136), que es de las implementaciones más completas que existen.
| Año | 2014; ABI estable en 2019; Swift 6 en 2024, con concurrencia estricta |
| Autoría | Chris Lattner —creador de LLVM— y equipo, Apple |
| Familia | Móvil / moderno; con Objective-C, Rust, Haskell y C# dentro |
| Paradigma | Multiparadigma: OO por protocolos, funcional e imperativo |
| Tipado | Estático, fuerte, con inferencia y opcionales en el tipo |
| Memoria | ARC: conteo automático de referencias, sin recolector y sin pausas |
| Ejecución | Compilado a nativo sobre LLVM |
| Estado | 🟢 Dominante en el ecosistema Apple; creciendo en servidor y embebido |
Chris Lattner había creado LLVM como proyecto de máster y lo había llevado a Apple, donde se convirtió en la base de todas sus herramientas. En 2010 empezó Swift en secreto, y Apple lo presentó en la WWDC de 2014 sin previo aviso.
El encargo era difícil: sustituir a Objective-C —treinta años de marcos y de código— sin romper nada. La solución fue la interoperabilidad total: Swift y Objective-C conviven en el mismo proyecto, y Swift importa las APIs de Objective-C con tipos precisos gracias a las anotaciones de nulabilidad que Apple añadió a Objective-C precisamente para eso.
Los hitos:
async/await, actores y concurrencia estructurada.Y desde 2015 es de código abierto, con versiones para Linux y Windows y un empuje serio hacia el servidor y los sistemas embebidos.
Uno, el conteo automático de referencias (clase 131):
class Nodo {
var siguiente: Nodo? // referencia FUERTE: mantiene vivo
weak var padre: Nodo? // DÉBIL: no cuenta, y se pone a nil al morir
unowned let dueño: Documento // sin dueño: no cuenta y NO se pone a nil
}
El compilador inserta retain y release, así que no hay recolector y no hay pausas — lo que
importa mucho en una animación a 120 fotogramas por segundo (clase 152).
Y el precio es el que la clase 131 explica: los ciclos no se recogen. Dos objetos que se apuntan
mutuamente con referencias fuertes no se liberan nunca, y el programador tiene que romper el
ciclo con weak o unowned.
Es el mismo modelo que Objective-C con ARC, que Rust con Rc/Weak y
que el conteo de referencias de Python y PHP — con la diferencia de que estos
dos últimos sí tienen un detector de ciclos adicional.
Dos, la concurrencia en el sistema de tipos (clase 136):
actor Banco {
private var saldo = 0.0 // ← nadie puede tocarlo desde fuera sin await
func depositar(_ x: Double) { saldo += x }
}
let b = Banco()
await b.depositar(100) // ← el await marca el cruce de frontera
Un actor aísla su estado: solo se accede desde dentro, y desde fuera hay que esperar. El compilador lo garantiza (clase 133).
Y Sendable es el otro lado: un tipo marcado como Sendable puede cruzar fronteras de
concurrencia con seguridad, y el compilador comprueba que no se envía nada que no lo sea. Es
exactamente el papel de Send/Sync en Rust, integrado en un lenguaje con ARC.
Y tres, los opcionales, que ya no sorprenden a nadie precisamente porque Swift ayudó a popularizarlos:
var nombre: String = "Ana" // no puede ser nil
var apodo: String? = nil // puede
if let a = apodo { ... } // desempaquetado seguro
guard let a = apodo else { return }
swift-format y SwiftLint para el estilo (clase 146).swift main.swift < entrada.txt # ejecutar como guion
swiftc -O main.swift -o venta # compilar optimizado
swift build && swift test # con Swift Package Manager (clases 143 y 139)
swift package init --type executable
Esta versión se escribe aquí y no está verificada en CI (clase 040).
import Foundation
guard let linea = readLine() else { exit(1) }
let v = linea.split(separator: " ").compactMap { Double($0) }
guard v.count == 3 else { exit(1) }
let total = v[0] * v[1] * (1 - v[2])
print(String(format: "Total: %.2f", total))
Lo que hay que ver.
guard let ... else es la forma idiomática de Swift para el camino de error: desempaqueta el
opcional y sale si no hay valor, dejando el resto de la función sin anidamiento. Compárese con el
! de Kotlin y de Dart, que afirma en lugar de comprobar.readLine() devuelve String? porque puede no haber línea — la posibilidad de fallo está en
el tipo, y el compilador obliga a tratarla (clase 116).compactMap convierte y descarta los nulos a la vez: Double($0) devuelve Double?, y
compactMap se queda con los que valen. Es un idioma muy del lenguaje.let es inmutable, var es mutable, y la convención es let por defecto (clase 102) — como
Rust, Kotlin y Scala.String(format:) viene de Foundation, que es la biblioteca de
Objective-C: la herencia se ve en la primera línea del programa.⏮️ Volver al Atlas · 🗂️ Todas las fichas · 🔗 Relacionadas: Objective-C · Rust · Kotlin · Dart · C++