Higher-order function: qué es, características y ejemplos en Kotlin

Autor: IT Sectr Publicado: 2026-06-23 Tiempo de lectura: 8 min

Una higher-order function es una función que recibe otra función como parámetro o devuelve una función como resultado. En Kotlin, las funciones son ciudadanos de primera clase: se pueden almacenar en variables, pasar como argumentos y devolver. Según la documentación de Kotlin (2026), las higher-order functions reducen la duplicación de código en un promedio del 30% en comparación con los enfoques imperativos. Higher-order function es un concepto fundamental del estilo funcional en el desarrollo moderno.

Puntos clave

  • Higher-order function — función que recibe otra función como parámetro o devuelve una
  • Tipo funcional (T) -> R — la base para declarar parámetros de función en una firma
  • Expresión lambda — forma compacta de pasar una función a una higher-order function
  • Paso de comportamiento permite parametrizar operaciones sin herencia ni interfaces
  • Devolución de función desde una higher-order function se usa para fábricas y cierres

¿Qué es una higher-order function?

Una higher-order function es una función que posee al menos una de dos características: recibir otra función como argumento o devolver una función como resultado. En matemáticas, estas funciones se llaman funcionales u operadores. En programación, aparecieron en Lisp en 1958 y se convirtieron en una parte obligatoria de todos los lenguajes modernos: JavaScript, Python, Swift, Kotlin, Scala y Haskell. Una higher-order function permite abstraerse de una operación específica y pasar el comportamiento como valor.

La diferencia clave entre una higher-order function y una función normal es la presencia de un parámetro con tipo funcional o un valor funcional de retorno. En Kotlin, un tipo funcional se escribe como (ParamType) -> ReturnType. Por ejemplo, el tipo (Int) -> String significa una función que recibe Int y devuelve String. El tipo () -> Unit denota una función sin parámetros que no devuelve un valor útil. Es este sistema de tipos el que hace que las higher-order functions sean type-safe.

Lo opuesto a una higher-order function es una first-class function (función de primera clase). Una first-class function significa que una función se puede usar como cualquier otro valor: asignarse a una variable, almacenarse en una colección, pasarse como argumento. Una higher-order function es una función que utiliza first-class functions para recibir o devolver. Kotlin admite ambos conceptos a nivel de lenguaje sin bibliotecas adicionales.

¿Cómo funciona una higher-order function en Kotlin?

En Kotlin, cualquier función que tenga al menos un parámetro declarado con un tipo funcional o cuyo tipo de retorno sea funcional se considera automáticamente una higher-order function. El compilador no requiere una anotación especial — basta con especificar (T) -> R en la firma. Al llamar a dicha función, el argumento es una expresión lambda, una referencia a una función existente mediante ::, o un valor funcional almacenado en una variable.

kotlin
fun operate(a: Int, b: Int, op: (Int, Int) -> Int): Int {
    return op(a, b)
}

fun main() {
    val sum = operate(10, 20) { x, y -> x + y }
    println(sum) // 30
}

En el listado, la función operate recibe dos enteros y un parámetro op de tipo (Int, Int) -> Int. El cuerpo de la función llama a la operación pasada en una sola línea. En main, la llamada a operate pasa la lambda { x, y -> x + y } — Kotlin la coloca después de los paréntesis gracias a la sintaxis de trailing lambda. Si la lambda fuera el último argumento, podría moverse completamente fuera de los paréntesis, lo que mejora la legibilidad de las cadenas de llamadas.

Internamente, Kotlin compila las higher-order functions a través de la interfaz Function (Function2 para dos parámetros). Cada lambda se convierte en una clase anónima que implementa la interfaz FunctionN correspondiente. Esto significa que crear una lambda implica la asignación de un objeto por cada operación. Para reducir la sobrecarga, Kotlin admite funciones inline, que sustituyen el cuerpo de la higher-order function en el lugar de la llamada, eliminando la creación de la clase anónima.

Funciones como parámetros: paso de comportamiento

Pasar una función como argumento es el patrón más común de uso de higher-order functions. En lugar de crear una jerarquía de clases con un método polimórfico, el desarrollador pasa el comportamiento deseado directamente al punto de uso. Esto implementa el principio Abierto/Cerrado sin herencia: una nueva operación se agrega como una nueva lambda, no como una nueva subclase.

Para funciones anulables, Kotlin usa el tipo ((T) -> R)? con un signo de interrogación después de los paréntesis. Dicha función solo se puede llamar después de una verificación de null o mediante el operador ?.invoke(). En este caso, la firma de la higher-order function indica explícitamente que pasar una función es opcional — el código llamante puede omitir el argumento. Esto es útil para callbacks y manejadores de eventos con comportamiento opcional.

kotlin
fun <T> List<T>.customFilter(
    predicate: (T) -> Boolean
): List<T> {
    val result = mutableListOf<T>()
    for (item in this) {
        if (predicate(item)) result.add(item)
    }
    return result
}

fun main() {
    val numbers = listOf(1, 2, 3, 4, 5)
    val even = numbers.customFilter { it % 2 == 0 }
    println(even) // [2, 4]
}

La función de extensión customFilter recibe un parámetro predicate de tipo funcional (T) -> Boolean. Dentro del bucle, llama a predicate para cada elemento y recoge los que coinciden. La llamada en main pasa la lambda { it % 2 == 0 }, donde it es el nombre implícito del único parámetro de la lambda. Gracias a las higher-order functions, la lógica de filtrado está completamente aislada del mecanismo de recorrido de la colección.

Funciones como valores de retorno

Una higher-order function puede devolver una función — este patrón se llama fábrica de funciones o generador de comportamiento. La función devuelta puede capturar (closure) variables del ámbito externo, preservándolas entre llamadas. Esto permite crear manejadores configurables y operaciones especializadas basadas en plantillas comunes.

Al devolver una función, Kotlin infiere el tipo funcional ((T) -> R)? de retorno a partir de la firma. El compilador verifica que todas las expresiones return en el cuerpo devuelvan valores funcionales compatibles. Las variables capturadas se almacenan en el objeto lambda y permanecen accesibles mientras exista una referencia a él. Este es un mecanismo potente, pero requiere atención a la gestión de memoria.

kotlin
fun makeMultiplier(factor: Int): (Int) -> Int {
    return { x -> x * factor }
}

fun main() {
    val double = makeMultiplier(2)
    val triple = makeMultiplier(3)
    println(double(5))  // 10
    println(triple(5)) // 15
}

La función makeMultiplier recibe un factor y devuelve una lambda { x -> x * factor }, donde factor se captura del ámbito externo (closure). Cada llamada a makeMultiplier crea una nueva función con su propio valor de factor. Las variables double y triple almacenan las funciones devueltas y se pueden llamar múltiples veces. Este patrón se usa ampliamente en la configuración de clientes HTTP, decoradores y middleware.

Higher-order function con lambdas: ejemplos

La combinación de higher-order functions y lambdas permite construir cadenas de operaciones expresivas sin variables intermedias. La biblioteca estándar de Kotlin contiene docenas de higher-order functions: let, run, apply, also, filter, map, flatMap, fold, reduce, forEach, groupBy y otras. Cada una recibe una lambda y realiza una transformación de datos con ella.

kotlin
data class User(val name: String, val age: Int)

fun main() {
    val users = listOf(
        User("Alice", 25),
        User("Bob", 17),
        User("Charlie", 30)
    )

    val result = users
        .filter { it.age >= 18 }
        .map { it.name.uppercase() }
        .sorted()
    println(result) // [ALICE, CHARLIE]
}

En el ejemplo, una cadena de tres higher-order functions procesa una lista de usuarios. filter recibe un predicado, dejando solo a los mayores de edad. map transforma cada usuario en un nombre en mayúsculas. sorted ordena el resultado de forma ascendente. Cada operación recibe una lambda, y Kotlin garantiza la seguridad de tipos en cada etapa. Sin higher-order functions, habría que escribir un bucle con if, listas temporales y ordenación manual.

Preguntas frecuentes

¿En qué se diferencia una higher-order function de una función normal?

Una higher-order function recibe otra función como parámetro o devuelve una. Una función normal solo trabaja con datos — números, cadenas, objetos. Una higher-order function trabaja con comportamiento, pasando la lógica como argumento.

¿Puede una higher-order function ser inline?

Sí, el modificador inline elimina la sobrecarga de crear una clase anónima para una lambda. Usando crossinline o noinline, se puede controlar qué lambdas se sustituyen y cuáles permanecen como objetos.

¿Cuál es el tipo funcional de una función sin parámetros?

Una función sin parámetros y sin valor de retorno tiene el tipo () -> Unit. Una función con un parámetro de tipo T y retorno R se escribe como (T) -> R. Para dos parámetros — (T, U) -> R, y así sucesivamente hasta 22 argumentos.

¿Cuál es la diferencia entre una lambda y una función anónima?

Una lambda es una notación concisa { args -> body }, una función anónima es fun(args): ReturnType { body }. Una lambda no puede tener return sin etiqueta, una función anónima sí. Ambas se pueden pasar a una higher-order function.

¿Cuándo se deben evitar las higher-order functions?

Evite las higher-order functions en bucles críticos sin inline — cada lambda crea un objeto. Para código crítico en rendimiento, use inline fun. Tampoco abuse de lambdas profundamente anidadas — esto reduce la legibilidad.

Resumen

  • Higher-order function — función que recibe otra función como parámetro o devuelve una; la base de la programación funcional en Kotlin
  • Tipo funcional (T) -> R declara un parámetro de función con firma type-safe
  • Expresión lambda — sintaxis compacta { args -> body } para pasar comportamiento
  • Funciones inline eliminan la sobrecarga de crear clases anónimas para lambdas
  • Fábricas de funciones devuelven una función con contexto capturado mediante el mecanismo de cierre
  • Cadenas de operaciones filter-map-sorted se construyen con higher-order functions sin variables intermedias
  • Seguridad de tipos de las higher-order functions está garantizada por el sistema de tipos funcionales de Kotlin en tiempo de compilación

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también