← Volver al blog

Declaración básica

Swift tiene un sistema de funciones muy expresivo: etiquetas de parámetros, valores por defecto y funciones como tipos. Todo lo que necesitas para escribir código reutilizable.

Las funciones son los bloques de construcción fundamentales de cualquier programa. Swift tiene un sistema de funciones muy expresivo con etiquetas de parámetros, valores por defecto y soporte de primera clase para funciones como tipos. En este post cubrimos todo lo que necesitas para escribir funciones claras y reutilizables.

Declaración básica

// Función sin parámetros ni retorno
func saludar() {
    print("Hola desde Swift")
}
saludar()

// Función con parámetros y valor de retorno
func sumar(_ a: Int, _ b: Int) -> Int {
    return a + b
}
let resultado = sumar(3, 5)  // 8

// En funciones de una sola expresión, puedes omitir 'return'
func multiplicar(_ a: Int, _ b: Int) -> Int {
    a * b
}
print(multiplicar(4, 6))  // 24

Etiquetas de parámetros — la gran diferencia de Swift

Swift distingue entre la etiqueta externa (la que usa quien llama a la función) y el nombre interno (el que usa el cuerpo de la función). Esto hace que las llamadas se lean casi como oraciones en inglés, o en tu idioma preferido.

// Sintaxis: func nombre(etiquetaExterna nombreInterno: Tipo)
func mover(desde origen: String, hasta destino: String) {
    print("Moviendo de \(origen) a \(destino)")
}
mover(desde: "Madrid", hasta: "Lima")  // se lee como una oración

// Usar _ para omitir la etiqueta en la llamada
func elevar(_ base: Double, al exponente: Int) -> Double {
    var resultado = 1.0
    for _ in 1...exponente { resultado *= base }
    return resultado
}
print(elevar(2, al: 10))  // 1024.0  — se lee: "elevar 2 al 10"

Valores por defecto

Los parámetros pueden tener valores por defecto, lo que los hace opcionales al llamar la función. Ponlos siempre al final de la lista de parámetros.

func conectar(a host: String, puerto: Int = 8080, seguro: Bool = true) {
    print("Conectando a \(host):\(puerto) — seguro: \(seguro)")
}

conectar(a: "ejemplo.com")                          // puerto 8080, seguro true
conectar(a: "ejemplo.com", puerto: 3000)            // seguro true por defecto
conectar(a: "ejemplo.com", puerto: 3000, seguro: false)  // todo explícito

Múltiples valores de retorno con tuplas

A diferencia de otros lenguajes, Swift permite retornar múltiples valores de una función usando tuplas. Es más limpio que usar parámetros inout o crear un struct solo para retornar dos valores.

func estadisticas(de numeros: [Int]) -> (minimo: Int, maximo: Int, promedio: Double) {
    let minimo   = numeros.min() ?? 0
    let maximo   = numeros.max() ?? 0
    let promedio = Double(numeros.reduce(0, +)) / Double(numeros.count)
    return (minimo, maximo, promedio)
}

let datos = [4, 8, 15, 16, 23, 42]
let stats = estadisticas(de: datos)

print("Mínimo: \(stats.minimo)")    // 4
print("Máximo: \(stats.maximo)")    // 42
print("Promedio: \(stats.promedio)") // 18.0

// Desestructurar directamente
let (min, max, avg) = estadisticas(de: datos)
print(min, max, avg)

Parámetros variádicos

Permiten pasar cualquier número de valores del mismo tipo. Dentro de la función se comportan como un array.

func sumarTodos(_ numeros: Int...) -> Int {
    numeros.reduce(0, +)
}

print(sumarTodos(1, 2, 3))         // 6
print(sumarTodos(10, 20, 30, 40))  // 100

// print() de Swift es variádico — por eso puedes pasar múltiples valores
print("a", "b", "c")  // "a b c"

Funciones como tipos — first-class functions

En Swift las funciones son tipos de primera clase: puedes almacenarlas en variables, pasarlas como parámetros y retornarlas desde otras funciones. Esta es la base de los closures y de cómo funcionan APIs como map, filter y sort.

func duplicar(_ n: Int) -> Int { n * 2 }
func triplicar(_ n: Int) -> Int { n * 3 }

// Almacenar una función en una variable
var operacion: (Int) -> Int = duplicar
print(operacion(5))  // 10

operacion = triplicar
print(operacion(5))  // 15

// Pasar una función como parámetro
func aplicar(_ operacion: (Int) -> Int, a numero: Int) -> Int {
    operacion(numero)
}
print(aplicar(duplicar, a: 7))   // 14
print(aplicar(triplicar, a: 7))  // 21

Closures — funciones anónimas

Los closures son funciones sin nombre. Son omnipresentes en Swift moderno, especialmente al trabajar con colecciones y código asíncrono.

let numeros = [3, 1, 4, 1, 5, 9, 2, 6]

// Forma completa
let ordenados = numeros.sorted(by: { (a: Int, b: Int) -> Bool in
    return a < b
})

// Forma abreviada con $0, $1 (shorthand arguments)
let ordenadosCorto = numeros.sorted { $0 < $1 }
print(ordenadosCorto)  // [1, 1, 2, 3, 4, 5, 6, 9]

// map — transforma cada elemento
let cuadrados = numeros.map { $0 * $0 }
print(cuadrados)  // [9, 1, 16, 1, 25, 81, 4, 36]

// filter — filtra elementos
let mayoresQueCinco = numeros.filter { $0 > 5 }
print(mayoresQueCinco)  // [9, 6]

// reduce — acumula en un solo valor
let total = numeros.reduce(0) { $0 + $1 }
print(total)  // 31

Resumen

  • Etiquetas externas: hacen las llamadas legibles como oraciones; usa _ para omitirlas.
  • Valores por defecto: hacen parámetros opcionales; ponlos al final.
  • Retorno múltiple con tuplas: más limpio que usar múltiples parámetros de salida.
  • Variádicos: acepta cualquier número de argumentos del mismo tipo.
  • Funciones como tipos: almacénalas, pásalas, retórnalas.
  • Closures: funciones anónimas; base de map, filter, sort y código asíncrono.

En el último post de esta serie veremos Clases y Estructuras — la diferencia fundamental entre tipos por valor y por referencia, y por qué en Swift moderno casi siempre preferirás struct.