Introducción a la programación funcional en Kotlin
Kotlin es un lenguaje moderno multiparadigma que combina orgánicamente la programación orientada a objetos y la programación funcional. El estilo funcional permite escribir código más predecible, conciso y testeable. En este artículo, analizaremos los conceptos clave de la programación funcional (PF) en Kotlin: funciones puras, inmutabilidad de datos, funciones de orden superior y trabajo con colecciones mediante map, filter y fold. El material está dirigido a desarrolladores que ya conocen los fundamentos de la sintaxis de Kotlin.
Funciones puras e inmutabilidad
¿Qué es una función pura?
Una función pura es una función que:
- Siempre devuelve el mismo resultado para los mismos argumentos (determinismo).
- No tiene efectos secundarios (no modifica el estado externo, no lee variables globales, no realiza entrada/salida).
Ejemplo de función pura:
fun sum(a: Int, b: Int): Int = a + bEjemplo de función impura (depende del estado externo):
var counter = 0fun impureSum(a: Int, b: Int): Int { counter++ // efecto secundario return a + b}Inmutabilidad (immutability)
En PF se acostumbra evitar modificar los datos después de su creación. En Kotlin para esto se utilizan:
valen lugar devarpara declarar referencias inmutables.- Colecciones inmutables:
listOf,mapOf,setOf. - Copia de objetos con cambios mediante
copy()para data-classes.
data class User(val name: String, val age: Int)
fun main() { val user = User("Alice", 25) val updatedUser = user.copy(age = 26) // creamos una nueva copia println(user) // User(name=Alice, age=25) println(updatedUser) // User(name=Alice, age=26)}Ventajas de la inmutabilidad: simplificación de la depuración, seguridad en hilos, predecibilidad del código.
Funciones de orden superior y expresiones lambda
Funciones como valores
En Kotlin las funciones pueden ser pasadas como argumentos, devueltas desde otras funciones y almacenadas en variables. Esta es la base del estilo funcional.
// Función que recibe otra funciónfun operateOnNumbers(a: Int, b: Int, operation: (Int, Int) -> Int): Int { return operation(a, b)}
fun main() { val sum = operateOnNumbers(5, 3) { x, y -> x + y } val product = operateOnNumbers(5, 3) { x, y -> x * y } println("Suma: $sum, Producto: $product")}Expresiones lambda
Una lambda es una función anónima escrita de forma compacta. Sintaxis: { argumentos -> cuerpo }.
val square: (Int) -> Int = { x -> x * x }val result = square(4) // 16
// Si hay un solo argumento, se puede usar el nombre implícito itval double: (Int) -> Int = { it * 2 }Funciones de orden superior incorporadas
Kotlin proporciona muchas funciones útiles para trabajar con colecciones:
map— transforma cada elemento.filter— conserva los elementos que cumplen la condición.fold— pliegue de la colección en un solo valor con un acumulador inicial.
fun main() { val numbers = listOf(1, 2, 3, 4, 5)
// map: elevar al cuadrado val squares = numbers.map { it * it } println(squares) // [1, 4, 9, 16, 25]
// filter: conservar solo los pares val evens = numbers.filter { it % 2 == 0 } println(evens) // [2, 4]
// fold: suma de todos los elementos val sum = numbers.fold(0) { acc, element -> acc + element } println(sum) // 15
// Cadena de llamadas: cuadrados pares val evenSquares = numbers .filter { it %