Funciones de alto orden y lambdas en Kotlin

Clase 21 de 35Curso de Kotlin

Resumen

Las funciones de alto orden son herramientas potentes que permiten pasar lambdas o funciones como parámetros. Esta característica, presente en lenguajes como Kotlin, nos brinda flexibilidad para manejar comportamientos de manera eficiente y clara.

¿Qué son las funciones de alto orden y las lambdas?

En Kotlin, una función de alto orden es aquella que recibe otra función (o lambda) como parámetro o devuelve una función como resultado. Una lambda es una variable que representa directamente una función, permitiéndonos escribir código conciso y expresivo.

Al definir una lambda, especificamos claramente los parámetros de entrada, señalamos con -> el tipo que retorna, y dentro de corchetes implementamos la acción de la lambda:

val formatearEmail: (Email) -> String = { email ->
    "${email.subject} de ${email.sender}"
}

Si deseamos referirnos al parámetro de entrada de manera implícita, podemos usar la palabra reservada it, siempre que haya un único parámetro.

¿Cómo aplicar la función map con lambdas a una lista?

La función map es una de las más usadas para aplicar transformaciones sobre listas. Mediante ésta, puedes pasar una lambda para modificar cada uno de los elementos:

val emailsFormateados = emails.map(formatearEmail)

Este fragmento muestra cómo map recibe como parámetro otra función o lambda y aplica la transformación indicada a cada elemento de la lista original.

¿Cómo usar la función forEach?

Otra función de alto orden muy utilizada es forEach. Esta permite recorrer elementos devolviendo cada ítem a través de una lambda, proporcionando otra forma más concisa de iterar sobre listas:

emailsFormateados.forEach { correo ->
    println(correo)
}

Si necesitas además el índice de cada iteración, Kotlin ofrece forEachIndexed que entrega también este dato en la lambda:

emailsFormateados.forEachIndexed { índice, correo ->
    println("Correo número $índice: $correo")
}

¿Qué son los callbacks con lambdas y cómo usarlos?

Los callbacks con lambdas permiten responder a distintos resultados dentro de la ejecución de una función. Este mecanismo, comúnmente implementado en operaciones asíncronas o validaciones, posibilita gestionar diversos enfoques según el éxito o fracaso del método llamado.

fun enviarEmail(email: Email, onSuccess: (Email, String) -> Unit, onError: (String, Int) -> Unit) {
    if (email.sender.contains("@")) {
        val mensaje = "Enviado a ${email.sender}"
        onSuccess(email, mensaje)
    } else {
        onError("Email inválido", 400)
    }
}

En este ejemplo, la función acepta dos callbacks: uno que se activa cuando la operación tiene éxito, devolviendo un mensaje adecuado, y otro para manejar posibles errores indicando un código concreto. Se invocan como una función convencional:

enviarEmail(emailUno, { e, mensaje ->
    println("${e.subject} $mensaje")
}, { mensaje, error ->
    println("Error: $mensaje Código: $error")
})

Esta estructura potencia tu código brindando claridad y organización.

¿Te ha resultado práctico este abordaje de funciones de alto orden y lambdas? Comparte cómo estás aplicando estos conceptos en tus propios proyectos.