Conceptos Fundamantales
Una función de orden superior es aquella que recibe otra función como parámetro o que devuelve una función como resultado. En esencia, permite tratar a las funciones como ciudadanos de primera clase.
Recibir una función como parámetro
Se puede pasar una función directamente en la lista de argumentos de otra función para ser ejecutada dentro de su contexto.
Retornar una función
Una función también puede construir y devolver una nueva función, permitiendo crear generadores o fábricas de lógica dinámica.
Ejemplos Comunes
Iteración de Colecciones
Para iterar sobre una colección, podemos aplicar una acción a cada elemento. A continuación, se muestra una implementación personalizada de este comportamiento:
inline fun IntArray.iterateAll(operation: (Int) -> Unit) {
for (item in this) operation(item)
}
Existen varias formas de invocar esta función en Kotlin:
fun main() {
val numbers = intArrayOf(10, 20, 30, 40, 50)
// 1. Pasando una referencia de función
numbers.iterateAll(::println)
// 2. Usando una expresión lambda dentro de los paréntesis
numbers.iterateAll({ println("Valor actual: $it") })
// 3. Sintaxis lambda final (trailing lambda): se omite el paréntesis
numbers.iterateAll { println("Procesado: $it") }
}
Transformación de Elementos
Esta técnica consiste en extraer cada elemento de un arreglo, transformarlo a otro tipo de dato y recolectar los resultados en una nueva lista.
inline fun <T> IntArray.transformElements(converter: (Int) -> T): List<T> {
val destination = ArrayList<T>(this.size)
for (num in this) {
destination.add(converter(num))
}
return destination
}
Casos de Uso Avanzados
Medición de Tiempo de Ejecución
Podemos crear un wrapper que envuelva un bloque de código y calcule cuánto tarda en ejecutarse:
fun measureDuration(task: () -> Unit) {
val startTime = System.currentTimeMillis()
task()
val finishTime = System.currentTimeMillis()
println("Duración: ${finishTime - startTime} ms")
}
Generador de Secuencias
Retornar una función nos permite mantener el estado internamente. Aquí, generamos una función que devuelve el siguiente número de la sucesión de Fibnoacci cada vez que se invoca:
fun createFibonacciGenerator(): () -> Long {
var prev = 0L
var curr = 1L
return {
val currentResult = prev
val nextVal = prev + curr
prev = curr
curr = nextVal
currentResult
}
}
fun main() {
measureDuration {
val getNextFib = createFibonacciGenerator()
repeat(10) {
println(getNextFib())
}
}
}